在C#中动态访问类及其属性

时间:2012-12-21 06:23:45

标签: c#

我需要访问类似strClassname.strPropertyName的内容。我会在程序执行中为strClassnamestrProperty名称设置不同的值。

请以正确的方式指导我。

3 个答案:

答案 0 :(得分:6)

听起来像是在尝试在运行时获取(或设置)对象上的属性值。所以这是最基本的方法:

public static object GetPropertyValue(object instance, string strPropertyName)
{
    Type type = instance.GetType();
    System.Reflection.PropertyInfo propertyInfo = type.GetProperty(strPropertyName);
    return propertyInfo.GetValue(instance, null);
}

...并设置一个值:

public static void SetPropertyValue(object instance, string strPropertyName, object newValue)
{
    Type type = instance.GetType();
    System.Reflection.PropertyInfo propertyInfo = type.GetProperty(strPropertyName);
    propertyInfo.SetValue(instance, newValue, null);
}

如果你试图获取一个类的属性名称,这里有一个函数:

public static IEnumerable<string> GetPropertyNames(string className)
{
    Type type = Type.GetType(className);
    return type.GetProperties().Select(p => p.Name);
}

假设您有100个对象,并且您希望在每个对象上获取Name属性的值,这是一个可以执行此操作的函数:

public static IEnumerable<String> GetNames(IEnumerable<Object> objects, string nameProperty = "Name")
{
    foreach (var instance in objects)
    {
        var type = instance.GetType();
        var property = type.GetProperty(nameProperty);
        yield return property.GetValue(instance, null) as string;
    }
}

答案 1 :(得分:5)

您可以使用反射:

要获取特定类型的属性名称,请使用方法Type.GetProperties。 Method返回PropertyInfo对象的数组,属性名称可通过PropertyInfo.Name属性获得。如果您只想获取所有属性的子集(例如,只有公共静态属性),请在调用GetProperties方法时使用BindingFlags。您必须至少指定两个标志,一个来自Public / NonPublic,另一个是Instance / Static标志。如果使用不带BindingFlags参数的GetProperties,则默认标志为Public + NonPublic + Instance。

以下示例显示了如何获取公共静态属性。

using System.Reflection;  // reflection namespace

// get all public static properties of MyClass type
PropertyInfo[] propertyInfos;
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public |
                                              BindingFlags.Static);
// sort properties by name
Array.Sort(propertyInfos,
        delegate(PropertyInfo propertyInfo1, PropertyInfo propertyInfo2)
        { return propertyInfo1.Name.CompareTo(propertyInfo2.Name); });

// write property names
foreach (PropertyInfo propertyInfo in propertyInfos)
{
  Console.WriteLine(propertyInfo.Name);
}

[Source]

答案 2 :(得分:0)

如果有一百个左右的类并且您知道要访问每个类的特定属性并且您知道每个类都将被实例化,那么肯定会考虑创建一个包含您希望的属性的接口访问前。

public interface INamed
{
    Name { get; }
}

使用示例:

var namedInstances = listOfClasses.Of<INamed>().Cast<INamed>();

foreach(var instance in namedInstances)
{
    var name = instance.Name;
}

另一方面,如果您不打算实例化这些类,如果“Name”属性是static或const,则可以尝试以下方法:

public interface INamed { } //Marker interface

public static class GetNamedHelper
{
    private static IEnumerable<Type> GetAssemblyTypes(IEnumerable<Assembly> assemblies)
    {
        if (assemblies == null) yield break;

        foreach (var assembly in assemblies.Where(assembly => assembly != null))
        {
            IEnumerable<Type> types;
            try
            {
                types = assembly.GetTypes().Where(t => t != null);
            }
            catch (ReflectionTypeLoadException rtle)
            {
                types = rtle.Types.Where(t => t != null);
            }
            foreach (var type in types)
                yield return type;
        }
    }

    private static readonly Type namedMarkerInterface = typeof (INamed);

    public static IEnumerable<string> GetNames(params Assembly[] assemblies)
    {
        var types = GetAssemblyTypes(assemblies)
            .Where(t => t.GetInterfaces().Any(intf => intf == namedMarkerInterface));

        foreach (var type in types)
        {
            //ex. public static string Name
            var prop = type.GetProperty("Name", BindingFlags.Public | BindingFlags.Static);
            if (prop == null || !prop.CanRead) continue;
            yield return prop.GetValue(null, null) as string;

            //ex. public const string Name
            var field = type.GetField("Name", BindingFlags.Public);
            if (field == null || !field.IsStatic) continue;
            yield return field.GetValue(null) as string;
        }
    }
}

无论如何,您需要知道要检查哪些类以及哪些类。