C# 将PropertyInfo转换为Func<&燃气轮机;代表
我有许多数据模型对象,它们的主键字段用DataAnnotations.KeyAttributes修饰:C# 将PropertyInfo转换为Func<&燃气轮机;代表,c#,C#,我有许多数据模型对象,它们的主键字段用DataAnnotations.KeyAttributes修饰: public class Example { [Key] [Column("FirstKey", Order = 1)] public Guid FirstKey { get; set; } [Key] [Column("SecondKey", Order = 2)] public Guid SecondKey { get; set; } [Column("Un
public class Example
{
[Key]
[Column("FirstKey", Order = 1)]
public Guid FirstKey { get; set; }
[Key]
[Column("SecondKey", Order = 2)]
public Guid SecondKey { get; set; }
[Column("Unimportant", Order = 3)]
public int UnimportantField {get; set; }
}
我可以使用PropertInfo选择数据模型对象的关键字段:
public static IEnumerable<PropertyInfo> GetKeyProperties<T>(this T source)
{
PropertyInfo[] properties = source.GetType().GetProperties();
return properties.Where(p => Attribute.IsDefined(p, typeof(KeyAttribute)));
}
我想创建一个泛型方法,它将构造一个Func委托,该委托将返回一个包含键字段的匿名对象
public static Func<T, object> GetKeyFunction<T>(this T source)
{
//construct Func<T, object> using IEnumerable<PropertyInfo>?
}
public static Func GetKeyFunction(此T源代码)
{
//使用IEnumerable构造Func?
}
因此,为示例的给定实例调用GetKeyFunction方法将返回一个Func委托。此委托应生成与GetKeyObjectExample方法等效的输出
如何实现该GetKeyFunction方法?不确定您想要实现什么,因为即使使用动态或匿名对象,您也需要知道关键字段的名称,但这样做可以实现您所述的方法(错误处理等省略):
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
运用系统动力学;
命名空间控制台应用程序11
{
类KeyAttribute:Attribute
{
}
公开课范例
{
[关键]
公共Guid FirstKey{get;set;}
[关键]
公共Guid第二密钥{get;set;}
公共int不重要字段{get;set;}
}
静态类程序
{
静态void Main(字符串[]参数)
{
示例e=新示例()
{
FirstKey=Guid.NewGuid(),
SecondKey=Guid.NewGuid()
};
var func=GetKeyFunction();
var key=func(e);
Console.WriteLine(key.FirstKey);
控制台。写入线(键。第二键);
}
公共静态函数GetKeyFunction()
{
返回(t)=>
{
var dyn=(IDictionary)新的ExpandooObject();
foreach(GetKeyProperties中的var p(typeof(T)))
{
动态添加(p.Name,p.GetValue(t));
}
返回dyn;
};
}
公共静态IEnumerable GetKeyProperties(类型t)
{
PropertyInfo[]properties=t.GetProperties();
返回properties.Where(p=>p.GetCustomAttributes().Any());
}
}
}
编辑
在阅读了一些注释之后,您可能会对这种方法产生兴趣,并将Equals和GetHashCode实现添加到动态对象中(该实现假设键字段的名称在equality中很重要)。感觉太多的代码和动态用于确定对象相等性,但是
与上面的代码相同,但有一个帮助器类来确定字典等式和哈希代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Dynamic;
namespace ConsoleApplication11
{
class KeyAttribute : Attribute
{
}
public class Example
{
[Key]
public Guid FirstKey { get; set; }
[Key]
public Guid SecondKey { get; set; }
public int UnimportantField { get; set; }
}
static class Program
{
static void Main(string[] args)
{
Example e = new Example()
{
FirstKey = Guid.NewGuid(),
SecondKey = Guid.NewGuid(),
UnimportantField = 0
};
var func = GetKeyFunction<Example>();
var key = func(e);
Console.WriteLine(key.FirstKey);
Console.WriteLine(key.SecondKey);
Console.WriteLine(key.Equals(key));
Console.WriteLine(key.GetHashCode());
Example e2 = new Example()
{
FirstKey = Guid.NewGuid(),
SecondKey = Guid.NewGuid(),
UnimportantField = 1
};
var key2 = func(e2);
Console.WriteLine(key2.FirstKey);
Console.WriteLine(key2.SecondKey);
Console.WriteLine(key.Equals(key2));
Console.WriteLine(key2.GetHashCode());
}
public static Func<T, dynamic> GetKeyFunction<T>()
{
return (t) =>
{
var dyn = (IDictionary<string, object>)new ExpandoObject();
foreach (var p in GetKeyProperties(typeof(T)))
{
dyn.Add(p.Name, p.GetValue(t));
}
dyn.Add("Equals", (Func<object, bool>)((o) =>
{
var comparer = new DictionaryComparer<string,object>();
return comparer.Equals(dyn as IDictionary<string,object>, o as IDictionary<string,object>);
}
));
dyn.Add("GetHashCode", (Func<int>)(() =>
{
var comparer = new DictionaryComparer<string, object>();
return comparer.GetHashCode(dyn as IDictionary<string, object>);
}
));
return dyn;
};
}
public static IEnumerable<PropertyInfo> GetKeyProperties(Type t)
{
PropertyInfo[] properties = t.GetProperties();
return properties.Where(p => p.GetCustomAttributes<KeyAttribute>().Any());
}
}
public class DictionaryComparer<TKey, TValue> : EqualityComparer<IDictionary<TKey, TValue>>
{
public DictionaryComparer()
{
}
public override bool Equals(IDictionary<TKey, TValue> x, IDictionary<TKey, TValue> y)
{
// early-exit checks
if (object.ReferenceEquals(x, y))
return true;
if (null == x || y == null)
return false;
if (x.Count != y.Count)
return false;
// check keys are the same
foreach (TKey k in x.Keys)
if (!y.ContainsKey(k))
return false;
// check values are the same
foreach (TKey k in x.Keys)
{
TValue v = x[k];
if (object.ReferenceEquals(v, null))
return object.ReferenceEquals(y[k], null);
if (!v.Equals(y[k]))
return false;
}
return true;
}
public override int GetHashCode(IDictionary<TKey, TValue> obj)
{
if (obj == null)
return 0;
int hash = 0;
foreach (KeyValuePair<TKey, TValue> pair in obj)
{
int key = pair.Key.GetHashCode(); // key cannot be null
int value = pair.Value != null ? pair.Value.GetHashCode() : 0;
hash ^= ShiftAndWrap(key, 2) ^ value;
}
return hash;
}
private static int ShiftAndWrap(int value, int positions)
{
positions = positions & 0x1F;
// Save the existing bit pattern, but interpret it as an unsigned integer.
uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
// Preserve the bits to be discarded.
uint wrapped = number >> (32 - positions);
// Shift and wrap the discarded bits.
return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
运用系统动力学;
命名空间控制台应用程序11
{
类KeyAttribute:Attribute
{
}
公开课范例
{
[关键]
公共Guid FirstKey{get;set;}
[关键]
公共Guid第二密钥{get;set;}
公共int不重要字段{get;set;}
}
静态类程序
{
静态void Main(字符串[]参数)
{
示例e=新示例()
{
FirstKey=Guid.NewGuid(),
SecondKey=Guid.NewGuid(),
不重要字段=0
};
var func=GetKeyFunction();
var key=func(e);
Console.WriteLine(key.FirstKey);
控制台。写入线(键。第二键);
Console.WriteLine(key.Equals(key));
Console.WriteLine(key.GetHashCode());
示例e2=新示例()
{
FirstKey=Guid.NewGuid(),
SecondKey=Guid.NewGuid(),
不重要字段=1
};
var-key2=func(e2);
Console.WriteLine(键2.FirstKey);
控制台。写入线(键2。第二键);
Console.WriteLine(key.Equals(key 2));
Console.WriteLine(key2.GetHashCode());
}
公共静态函数GetKeyFunction()
{
返回(t)=>
{
var dyn=(IDictionary)新的ExpandooObject();
foreach(GetKeyProperties中的var p(typeof(T)))
{
动态添加(p.Name,p.GetValue(t));
}
动态添加(“等于”,“函数”((o)=>
{
var comparer=新字典comparer();
返回比较器.Equals(dyn作为IDictionary,o作为IDictionary);
}
));
dyn.Add(“GetHashCode”,(Func)(()=>
{
var comparer=新字典comparer();
返回comparer.GetHashCode(dyn作为IDictionary);
}
));
返回dyn;
};
}
公共静态IEnumerable GetKeyProperties(类型t)
{
PropertyInfo[]properties=t.GetProperties();
返回properties.Where(p=>p.GetCustomAttributes().Any());
}
}
公共类词典比较程序:EqualityComparer
{
公共词典比较程序()
{
}
公共覆盖布尔等于(IDictionary x,IDictionary y)
{
//提前出境检查
if(object.ReferenceEquals(x,y))
返回true;
if(null==x | | y==null)
返回false;
如果(x.Count!=y.Count)
返回false;
//检查钥匙是否相同
foreach(x.Keys中的tk键)
如果(!y.ContainsKey(k))
返回f
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Dynamic;
namespace ConsoleApplication11
{
class KeyAttribute : Attribute
{
}
public class Example
{
[Key]
public Guid FirstKey { get; set; }
[Key]
public Guid SecondKey { get; set; }
public int UnimportantField { get; set; }
}
static class Program
{
static void Main(string[] args)
{
Example e = new Example()
{
FirstKey = Guid.NewGuid(),
SecondKey = Guid.NewGuid()
};
var func = GetKeyFunction<Example>();
var key = func(e);
Console.WriteLine(key.FirstKey);
Console.WriteLine(key.SecondKey);
}
public static Func<T, dynamic> GetKeyFunction<T>()
{
return (t) =>
{
var dyn = (IDictionary<string, object>)new ExpandoObject();
foreach (var p in GetKeyProperties(typeof(T)))
{
dyn.Add(p.Name, p.GetValue(t));
}
return dyn;
};
}
public static IEnumerable<PropertyInfo> GetKeyProperties(Type t)
{
PropertyInfo[] properties = t.GetProperties();
return properties.Where(p => p.GetCustomAttributes<KeyAttribute>().Any());
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Dynamic;
namespace ConsoleApplication11
{
class KeyAttribute : Attribute
{
}
public class Example
{
[Key]
public Guid FirstKey { get; set; }
[Key]
public Guid SecondKey { get; set; }
public int UnimportantField { get; set; }
}
static class Program
{
static void Main(string[] args)
{
Example e = new Example()
{
FirstKey = Guid.NewGuid(),
SecondKey = Guid.NewGuid(),
UnimportantField = 0
};
var func = GetKeyFunction<Example>();
var key = func(e);
Console.WriteLine(key.FirstKey);
Console.WriteLine(key.SecondKey);
Console.WriteLine(key.Equals(key));
Console.WriteLine(key.GetHashCode());
Example e2 = new Example()
{
FirstKey = Guid.NewGuid(),
SecondKey = Guid.NewGuid(),
UnimportantField = 1
};
var key2 = func(e2);
Console.WriteLine(key2.FirstKey);
Console.WriteLine(key2.SecondKey);
Console.WriteLine(key.Equals(key2));
Console.WriteLine(key2.GetHashCode());
}
public static Func<T, dynamic> GetKeyFunction<T>()
{
return (t) =>
{
var dyn = (IDictionary<string, object>)new ExpandoObject();
foreach (var p in GetKeyProperties(typeof(T)))
{
dyn.Add(p.Name, p.GetValue(t));
}
dyn.Add("Equals", (Func<object, bool>)((o) =>
{
var comparer = new DictionaryComparer<string,object>();
return comparer.Equals(dyn as IDictionary<string,object>, o as IDictionary<string,object>);
}
));
dyn.Add("GetHashCode", (Func<int>)(() =>
{
var comparer = new DictionaryComparer<string, object>();
return comparer.GetHashCode(dyn as IDictionary<string, object>);
}
));
return dyn;
};
}
public static IEnumerable<PropertyInfo> GetKeyProperties(Type t)
{
PropertyInfo[] properties = t.GetProperties();
return properties.Where(p => p.GetCustomAttributes<KeyAttribute>().Any());
}
}
public class DictionaryComparer<TKey, TValue> : EqualityComparer<IDictionary<TKey, TValue>>
{
public DictionaryComparer()
{
}
public override bool Equals(IDictionary<TKey, TValue> x, IDictionary<TKey, TValue> y)
{
// early-exit checks
if (object.ReferenceEquals(x, y))
return true;
if (null == x || y == null)
return false;
if (x.Count != y.Count)
return false;
// check keys are the same
foreach (TKey k in x.Keys)
if (!y.ContainsKey(k))
return false;
// check values are the same
foreach (TKey k in x.Keys)
{
TValue v = x[k];
if (object.ReferenceEquals(v, null))
return object.ReferenceEquals(y[k], null);
if (!v.Equals(y[k]))
return false;
}
return true;
}
public override int GetHashCode(IDictionary<TKey, TValue> obj)
{
if (obj == null)
return 0;
int hash = 0;
foreach (KeyValuePair<TKey, TValue> pair in obj)
{
int key = pair.Key.GetHashCode(); // key cannot be null
int value = pair.Value != null ? pair.Value.GetHashCode() : 0;
hash ^= ShiftAndWrap(key, 2) ^ value;
}
return hash;
}
private static int ShiftAndWrap(int value, int positions)
{
positions = positions & 0x1F;
// Save the existing bit pattern, but interpret it as an unsigned integer.
uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
// Preserve the bits to be discarded.
uint wrapped = number >> (32 - positions);
// Shift and wrap the discarded bits.
return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
}
}
}