programing

C # : 형식의 모든 공용 (가져 오기 및 설정 모두) 문자열 속성을 가져 오는 방법

randomtip 2021. 1. 14. 08:14
반응형

C # : 형식의 모든 공용 (가져 오기 및 설정 모두) 문자열 속성을 가져 오는 방법


나는 일반 객체의 목록을 가서 유형의 모든 속성을 대체 할 방법을 만들려고 노력하고 있어요 string중 하나입니다 null또는 교체 빈을.

이 작업을 수행하는 좋은 방법은 무엇입니까?

나는 이런 종류의 ... 껍질 ... 지금까지 :

public static void ReplaceEmptyStrings<T>(List<T> list, string replacement)
{
    var properties = typeof(T).GetProperties( -- What BindingFlags? -- );

    foreach(var p in properties)
    {
        foreach(var item in list)
        {
            if(string.IsNullOrEmpty((string) p.GetValue(item, null)))
                p.SetValue(item, replacement, null);
        }
    }
}

따라서 다음과 같은 유형의 모든 속성을 어떻게 찾을 수 있습니까?

  • 유형 string
  • 공개 get
  • 공개 set

    ?


이 테스트 클래스를 만들었습니다.

class TestSubject
{
    public string Public;
    private string Private;

    public string PublicPublic { get; set; }
    public string PublicPrivate { get; private set; }
    public string PrivatePublic { private get; set; }
    private string PrivatePrivate { get; set; }
}

다음은 작동하지 않습니다.

var properties = typeof(TestSubject)
        .GetProperties(BindingFlags.Instance|BindingFlags.Public)
        .Where(ø => ø.CanRead && ø.CanWrite)
        .Where(ø => ø.PropertyType == typeof(string));

내가 거기에 도착한 속성의 이름을 인쇄하면 다음을 얻습니다.

공개 공개 공개 개인 비공개 공개

즉, 두 가지 속성을 너무 많이 얻습니다.


참고 : 이것은 아마도 더 나은 방법으로 수행 될 수 있습니다 ... 중첩 된 foreach 및 반사를 사용하여 여기에 모두 ...하지만 훌륭한 대안 아이디어가 있으면 배우고 싶은 이유를 알려주십시오!


코드를 다시 작성했습니다. LINQ 또는 var를 사용하지 않습니다.

public static void ReplaceEmptyStrings<T>(List<T> list, string replacement)
{
    PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (PropertyInfo p in properties)
    {
        // Only work with strings
        if (p.PropertyType != typeof(string)) { continue; }

        // If not writable then cannot null it; if not readable then cannot check it's value
        if (!p.CanWrite || !p.CanRead) { continue; }

        MethodInfo mget = p.GetGetMethod(false);
        MethodInfo mset = p.GetSetMethod(false);

        // Get and set methods have to be public
        if (mget == null) { continue; }
        if (mset == null) { continue; }

        foreach (T item in list)
        {
            if (string.IsNullOrEmpty((string)p.GetValue(item, null)))
            {
                p.SetValue(item, replacement, null);
            }
        }
    }
}

.NET과 같은 속성을 찾을 수 BindingFlags.Public | BindingFlags.Instance있습니다. 그런 다음 CanWrite 및 CanRead 속성을 확인하여 각 PropertyInfo 인스턴스를 검사하여 읽기 및 / 또는 쓰기 가능한지 여부를 확인해야합니다.

업데이트 : 코드 예제

PropertyInfo[] props = yourClassInstance.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < props.Length; i++)
{
    if (props[i].PropertyType == typeof(string) && props[i].CanWrite)
    {
        // do your update
    }
}

업데이트 후 더 자세히 조사했습니다. GetGetMethod 및 GetSetMethod에서 반환 된 MethodInfo 개체도 검사하면 대상에 도달 할 것입니다.

 var properties = typeof(TestSubject).GetProperties(BindingFlags.Instance | BindingFlags.Public)
        .Where(ø => ø.CanRead && ø.CanWrite)
        .Where(ø => ø.PropertyType == typeof(string))
        .Where(ø => ø.GetGetMethod(true).IsPublic)
        .Where(ø => ø.GetSetMethod(true).IsPublic);

기본적으로이 두 메서드는 공용 getter 및 setter 만 반환하지만 (이와 같은 경우 NullReferenceException 발생) true위와 같이 전달 하면 개인 메서드 도 반환됩니다. 그런 다음 IsPublic(또는 IsPrivate) 속성을 검사 할 수 있습니다.


If you don't specify any binding flags you will get the public, instance properties -- which is what you want. But then you will need to check if the PropertyType on the PropertyInfo object is of type String. Unless you know in advance, you'll also need to check whether the property is readable/writable as @Fredrik indicates.

using System.Linq;

public static void ReplaceEmptyStrings<T>(List<T> list, string replacement)
{
    var properties = typeof(T).GetProperties()
                              .Where( p => p.PropertyType == typeof(string) );
    foreach(var p in properties)
    {
        foreach(var item in list)
        {
            if(string.IsNullOrEmpty((string) p.GetValue(item, null)))
                p.SetValue(item, replacement, null);
        }
    }
}

http://jefferytay.wordpress.com/2010/05/03/simple-and-useful-tostring/

for a tostring override method which allows you to get all the properties of the class


BindingFlags.Public | BindingFlags.Instance should do it

GetSetMethod()


I suggest a different approach: AOP.
You can intercept the setter and set the desired value to a valid one. With PostSharp it's quite easy.


I agree with other answers, but I prefer to refactor the search itself to be easly queried with Linq, so the query could be as follow:

        var asm = Assembly.GetExecutingAssembly();
        var properties = (from prop
                              in asm.GetType()
                                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                          where 
                            prop.PropertyType == typeof (string) && 
                            prop.CanWrite && 
                            prop.CanRead
                          select prop).ToList();
        properties.ForEach(p => Debug.WriteLine(p.Name));

I took for my example the Assembly type, which hasn't read/write string properties, but if the same code search for just read properties, the result will be:

  • CodeBase
  • EscapedCodeBase
  • FullName
  • Location
  • ImageRuntimeVersion

Which are the string read-only Assembly type properties

ReferenceURL : https://stackoverflow.com/questions/824802/c-how-to-get-all-public-both-get-and-set-string-properties-of-a-type

반응형