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