C# 使用字符串访问属性

C# 使用字符串访问属性,c#,C#,给定一个与对象字段同名的字符串,如何获取对该对象字段的引用 例如,假设我将一个名为“field1”的字符串传递给GetFieldByStr方法,并且该对象具有字段名field1,那么如何获取对field1对象的引用?我假设以某种方式使用反射 class Example { private FieldExample attr1; void GetFieldByStr(String str) { // We get passed in "field1" as a strin

给定一个与对象字段同名的字符串,如何获取对该对象字段的引用

例如,假设我将一个名为“field1”的字符串传递给GetFieldByStr方法,并且该对象具有字段名field1,那么如何获取对field1对象的引用?我假设以某种方式使用反射

class Example {
   private FieldExample attr1;

   void GetFieldByStr(String str) {
      // We get passed in "field1" as a string, now I want 
      // to get the field1 attribute.
   }
}
可以使用(或取决于是否需要字段或属性)

例如:

void GetAttributesByStr(String str) {
    FieldInfo attributeInfo = this.GetType().GetField(str); // you might want to use some Binding flags here like BindingFlags.Instance and BindingFlags.Public

    attributeInfo.GetValue(this); // assign this to something or return it as an object
}

这里有一个不依赖反射的想法。缺点是它需要一些设置。您甚至可以定义一些自定义属性,并使用一些巧妙的代码在应用程序启动时自动执行设置

interface IAttributeStore
{
    T GetAttribute<T>(string key);
}

class Example : IAttributeStore
{
    public int ExampleID { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    static Dictionary<string, Delegate> _AttributeAccessors;

    static Example()
    {
        _AttributeAccessors = new Dictionary<string, Delegate>();

        _AttributeAccessors.Add("ExampleID", new Func<Example, int>((example) => example.ExampleID));
        _AttributeAccessors.Add("FirstName", new Func<Example, string>((example) => example.FirstName));
        _AttributeAccessors.Add("LastName", new Func<Example, string>((example) => example.LastName));
    }

    #region IAttributeStore Members

    public T GetAttribute<T>(string key)
    {
        Delegate accessor;
        if (_AttributeAccessors.TryGetValue(key, out accessor))
        {
            Func<Example, T> func = accessor as Func<Example, T>;
            if (func != null)
                return func(this);
            else
                throw new Exception(string.Format("The attribute with the given key \"{0}\" is not of type [{1}].", key, typeof(T).FullName));
        }
        else
        {
            throw new ArgumentException(string.Format("No attribute exists with the given key: \"{0}\".", key), "key");
        }
    }

    #endregion
}

class Program
{
    static void Main(string[] args)
    {
        Example example = new Example() { ExampleID = 12345, FirstName = "Funky", LastName = "Town" };

        Console.WriteLine(example.GetAttribute<int>("ExampleID"));
        Console.WriteLine(example.GetAttribute<string>("FirstName"));
        Console.WriteLine(example.GetAttribute<string>("LastName"));
    }
}
interface-testore
{
T GetAttribute(字符串键);
}
类示例:IAttributeStore
{
public int ExampleID{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
静态字典\u属性访问器;
静态示例()
{
_AttributeAccessors=新字典();
_AttributeAccessors.Add(“ExampleID”,newfunc((example)=>example.ExampleID));
_AttributeAccessors.Add(“FirstName”,newfunc((示例)=>example.FirstName));
_AttributeAccessors.Add(“LastName”,newfunc((示例)=>example.LastName));
}
#地区测试成员
公共gett属性(字符串键)
{
委托访问器;
if(_AttributeAccessors.TryGetValue(键,出访问器))
{
Func Func=作为Func的访问器;
如果(func!=null)
返回func(this);
其他的
抛出新异常(string.Format(“具有给定键\“{0}\”的属性不是类型[{1}]。”,键,typeof(T.FullName));
}
其他的
{
抛出新的ArgumentException(string.Format(“给定的键不存在属性:\”{0}\”,key),“key”);
}
}
#端区
}
班级计划
{
静态void Main(字符串[]参数)
{
示例=新示例(){ExampleID=12345,FirstName=“Funky”,LastName=“Town”};
WriteLine(example.GetAttribute(“ExampleID”);
WriteLine(例如.GetAttribute(“FirstName”));
WriteLine(例如.GetAttribute(“LastName”);
}
}
更新:这对我来说似乎很有趣,所以我设计了一个替代实现,它利用属性和扩展方法,而不是接口。这样做的好处是,每个类只需要很少的代码(您只需要添加属性),而设置委托的代码仅在应用程序实际从特定类请求属性时运行

我必须感谢Marc Gravell的回答,因为他回答了如何动态创建一个委托来获取给定PropertyInfo对象的属性

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
class AttributeStoreAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
class StoredAttributeAttribute : Attribute
{
    public string Key { get; set; }
}

public static class AttributeStore<T>
{
    static Dictionary<string, Delegate> _AttributeAccessors;

    public static void Initialize()
    {
        _AttributeAccessors = new Dictionary<string, Delegate>();

        Type type = typeof(T);

        // let's keep it simple and just do properties for now
        foreach (var property in type.GetProperties())
        {
            var attributes = property.GetCustomAttributes(typeof(StoredAttributeAttribute), true);
            if (attributes != null && attributes.Length > 0)
            {
                foreach (object objAttribute in attributes)
                {
                    StoredAttributeAttribute attribute = objAttribute as StoredAttributeAttribute;
                    if (attribute != null)
                    {
                        string key = attribute.Key;

                        // use the property name by default
                        if (string.IsNullOrEmpty(key))
                            key = property.Name;

                        if (_AttributeAccessors.ContainsKey(key))
                            throw new Exception(string.Format("An attribute accessor has already been defined for the given key \"{0}\".", key));

                        Type typeOfFunc = typeof(Func<,>).MakeGenericType(type, property.PropertyType);
                        Delegate accessor = Delegate.CreateDelegate(typeOfFunc, null, property.GetGetMethod());
                        _AttributeAccessors.Add(key, accessor);
                    }
                }
            }
        }
    }

    public static object GetAttribute(T store, string key)
    {
        if (_AttributeAccessors == null)
            Initialize();

        Delegate accessor;
        if (_AttributeAccessors.TryGetValue(key, out accessor))
        {
            return accessor.DynamicInvoke(store);
        }
        else
        {
            throw new ArgumentException(string.Format("No attribute exists with the given key: \"{0}\" on attribute store [{1}].", key, typeof(T).FullName), "key");
        }
    }

    public static TResult GetAttribute<TResult>(T store, string key)
    {
        if (_AttributeAccessors == null)
            Initialize();

        Delegate accessor;
        if (_AttributeAccessors.TryGetValue(key, out accessor))
        {
            Func<T, TResult> func = accessor as Func<T, TResult>;
            if (func != null)
                return func(store);
            else
                throw new Exception(string.Format("The attribute with the given key \"{0}\" on attribute store [{1}] is not of type [{2}].", key, typeof(T).FullName, typeof(TResult).FullName));
        }
        else
        {
            throw new ArgumentException(string.Format("No attribute exists with the given key: \"{0}\" on attribute store [{1}].", key, typeof(T).FullName), "key");
        }
    }
}

public static class AttributeStoreExtensions
{
    public static object GetAttribute<T>(this T store, string key)
    {
        return AttributeStore<T>.GetAttribute(store, key);
    }

    public static TResult GetAttribute<T, TResult>(this T store, string key)
    {
        return AttributeStore<T>.GetAttribute<TResult>(store, key);
    }
}

[AttributeStore]
class Example
{
    [StoredAttribute]
    public int ExampleID { get; set; }

    [StoredAttribute]
    public string FirstName { get; set; }

    [StoredAttribute]
    public string LastName { get; set; }
}

[AttributeStore]
class Example2
{
    [StoredAttribute]
    [StoredAttribute(Key = "ID")]
    public int ExampleID { get; set; }

    [StoredAttribute]
    [StoredAttribute(Key = "First")]
    public string FirstName { get; set; }

    [StoredAttribute]
    [StoredAttribute(Key = "Last")]
    public string LastName { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Example example = new Example() { ExampleID = 12345, FirstName = "Funky", LastName = "Town" };

        Console.WriteLine(example.GetAttribute("ExampleID"));
        Console.WriteLine(example.GetAttribute("FirstName"));
        Console.WriteLine(example.GetAttribute("LastName"));

        Example2 example2 = new Example2() { ExampleID = 12345, FirstName = "Funky", LastName = "Town" };

        // access attributes by the default key (property name)
        Console.WriteLine(example2.GetAttribute("ExampleID"));
        Console.WriteLine(example2.GetAttribute("FirstName"));
        Console.WriteLine(example2.GetAttribute("LastName"));

        // access attributes by the explicitly specified key
        Console.WriteLine(example2.GetAttribute("ID"));
        Console.WriteLine(example2.GetAttribute("First"));
        Console.WriteLine(example2.GetAttribute("Last"));
    }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface,AllowMultiple=false,Inherited=true)]
类AttributesToreatAttribute:属性
{
}
[AttributeUsage(AttributeTargets.Property,AllowMultiple=true,Inherited=true)]
类StoredAttributeAttribute:属性
{
公共字符串密钥{get;set;}
}
公共静态类AttributeStore
{
静态字典\u属性访问器;
公共静态void Initialize()
{
_AttributeAccessors=新字典();
类型=类型(T);
//让我们保持简单,现在只做属性
foreach(类型.GetProperties()中的var属性)
{
var attributes=property.GetCustomAttributes(typeof(StoredAttributeAttribute),true);
if(attributes!=null&&attributes.Length>0)
{
foreach(属性中的对象objAttribute)
{
StoredAttributeAttribute=对象属性为StoredAttributeAttribute;
if(属性!=null)
{
字符串键=attribute.key;
//默认情况下使用属性名称
if(string.IsNullOrEmpty(key))
key=property.Name;
if(_AttributeAccessors.ContainsKey(键))
抛出新异常(string.Format(“已为给定键\“{0}\”,key定义了属性访问器));
typeOfFunc=typeof(Func).MakeGenericType(Type,property.PropertyType);
Delegate accessor=Delegate.CreateDelegate(typeOfFunc,null,property.getMethod());
_AttributeAccessors.Add(键,访问器);
}
}
}
}
}
公共静态对象GetAttribute(T存储,字符串键)
{
if(_AttributeAccessors==null)
初始化();
委托访问器;
if(_AttributeAccessors.TryGetValue(键,出访问器))
{
返回访问器.DynamicInvoke(存储);
}
其他的
{
抛出新的ArgumentException(string.Format(“属性存储[{1}]上不存在具有给定键:\“{0}\”的属性)。”,键,typeof(T.FullName),“键”);
}
}
公共静态TResult GetAttribute(T存储,字符串键)
{
if(_AttributeAccessors==null)
初始化();
委托访问器;
if(_AttributeAccessors.TryGetValue(键,出访问器))
{
Func Func=作为Func的访问器;
如果(func!=null)
返回func(存储);
其他的
抛出新异常(string.Format(“属性存储[{1}]上具有给定键\“{0}\”的属性不属于类型[{2}]。”,键,typeof(T).FullName,typeof(TResult.FullName));
}
其他的
{
抛出新的ArgumentException(string.Format(“属性存储[{1}]上不存在具有给定键:\“{0}\”的属性)。”,键,typeof(T.FullName),“键”);
FieldInfo field = typeof(Example).GetField(str);
object value = field.GetValue(this);
var prop = this.GetType().GetProperty(str);
prop.GetValue(prop, null);