给定一个与对象字段名称相同的字符串,如何获取对象字段的引用?
例如,假设我将名为“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.
}
}
答案 0 :(得分:4)
FieldInfo field = typeof(Example).GetField(str);
object value = field.GetValue(this);
(对于属性,请使用PropertyInfo
)
请注意value
是一个对象;为了对它做任何有用的事情,你需要将它强制转换为某个类或接口(或者在C#4中使用dynamic
。)
答案 1 :(得分:2)
您可以使用Reflection library(FieldInfo或PropertyInfo取决于您是否需要字段或属性)
示例:
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
}
答案 2 :(得分:2)
这是一个不依赖于反思的想法。缺点是它需要一些设置。您甚至可以定义一些自定义属性,并使用一些聪明的代码在应用程序启动时自动执行设置。
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"));
}
}
更新:这对我来说似乎很有趣,所以我将一个替代实现集合在一起,它使用属性和扩展方法而不是接口。关于这一点的好处是它每个类只需要很少的代码(你只需要添加属性),并且只有当应用程序实际请求来自特定类的属性时,才会运行设置委托的代码。
我必须赞扬Marc Gravell对this question的答案,了解如何动态创建委托以获取给定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"));
}
}
答案 3 :(得分:0)
对于属性。
var prop = this.GetType().GetProperty(str);
prop.GetValue(prop, null);