- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有许多数据模型对象,它们的主键字段用 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("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)));
}
我还可以手动构建一个包含给定类的键字段的匿名对象:
public static object GetKeyObjectForExample(Example example)
{
return new { example.FirstKey, example.SecondKey };
}
我想创建一个通用方法来构造一个 Func 委托(delegate),该委托(delegate)将返回一个包含键字段的匿名对象。
public static Func<T, object> GetKeyFunction<T>(this T source)
{
//construct Func<T, object> using IEnumerable<PropertyInfo>?
}
因此,为给定的 Example 实例调用 GetKeyFunction 方法将返回一个 Func 委托(delegate)。此委托(delegate)应生成与 GetKeyObjectForExample 方法等效的输出。
如何实现 GetKeyFunction 方法?
最佳答案
不确定您要实现的确切目标,因为即使使用动态或匿名对象,您仍然需要知道关键字段的名称,但像这样的方法可以解决您声明的方法(错误处理等省略):
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());
}
}
}
编辑
阅读一些评论后,您可能会喜欢上这种方法,并向您的动态对象添加一个 Equals 和 GetHashCode 实现(此实现假定关键字段的名称在相等性方面很重要)。感觉像确定对象相等性的代码和动态太多了,但是......
与上面相同的代码,但有一个辅助类来确定字典相等性和哈希码。
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);
}
}
}
关于c# - 将 PropertyInfo 转换为 Func<> 委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23159957/
我看了很多文章,但我仍然不清楚我们通常创建的普通委托(delegate)和多播委托(delegate)之间的区别。 public delegate void MyMethodHandler(objec
考虑以下几点: Action a1 = new Action(_insert); Action a2 = new Action(a1); a2 指的是什么?它是 a1,a1 的浅拷贝还是 a1 的深拷
我希望这听起来像是一个显而易见的问题,但是委托(delegate)返回类型是否也必须与其委托(delegate)的方法的返回类型相匹配? EG,像这样: public static void Save
我想使用 Kotlin 委托(delegate),但我不想在委托(delegate)人之外创建委托(delegate)。委托(delegate)的所有示例都如下所示: interface Worker
class SuperClass { var delegate : SuperClassDelegate? } protocol SuperClassDelegate { func d
我有一个加载 View 的 View ,需要将 View 推送到主导航 Controller 。 我已经为每个 View 设置了一个委托(delegate),并且基本上使我的调用沿着“链”返回到主导航
为简单起见,假设我想创建一个自定义 UITextField 并向其添加一个简单的行为;也就是说,如果文本字段成为第一响应者,背景颜色将变为绿色。 为此,在我的自定义类中,我必须将该类设置为委托(del
我非常有信心我应该能够使用非静态方法的委托(delegate),但下面给了我一个错误: public class TestClass { private delegate void TestD
在 C# 中不能从 System.Delegate 或 System.MulticastDelegate 继承。只要您声明标准的“运行时托管”方法,就完全可以在 MSIL 中执行此操作。但是,每次我向
我在 Storyboard 中定义了一个 iPad 界面,带有一个 SplitViewController。我想将 SplitViewController 的委托(delegate)设置为指向详细 C
我有几个解析器。有一个顶级的可以委托(delegate)给另一个。 Parser我们从 Reader 中获取他们的输入(可变)。我只想要一个 Parser为了能够一次解析,只有一个解析器应该有 Rea
一直以来我都在阅读关于反射的文章,每个人都在说:“反射很慢”,“反射很慢”。 现在我决定测试速度有多慢,令我惊讶的是,使用反射创建的委托(delegate)实际上是使用 lambda 创建的委托(de
在 Xcode 4.5 中启动了 Cocos2D 2.1 模板(没有物理引擎),针对 iOS 6 和 iPad。在 CDAudioManager.m 文件中,以下代码... AVAudioSessio
以下是来自未管理的 dll 的函数代码。它接受一个函数指针作为参数,并简单地返回被调用函数返回的值。 extern __declspec(dllexport) int _stdcall callDe
//NewCharts.h #import @interface NewCharts : UIViewController @property(nonatomic,retain)IBOutlet U
鉴于以下 MSDN 示例代码,为什么我不能定义 Action 委托(delegate)“内联”: public static void Main(string[] args) { Action
在虚幻引擎中,UFUNCTION用于通过附加说明符来丰富功能,以用于蓝图使用、复制和委托(delegate)。 然而,一些委托(delegate)类型似乎不允许绑定(bind) UFUNCTION(如
我刚刚将照片选择器放入我的项目中,一切正常。唯一的事情是它坚持在我设置委托(delegate)的地方给我以下警告 - Assigning to 'id' from incompatible type
我有一个 UIImageView 的子类,并且想将 self 作为参数传递给委托(delegate)。我在 MyImageView 之前收到错误“预期 ')'”。我需要将对象传递给委托(delegat
我正在开发 iOS 10 的语音转文本功能。 我希望调用 SFSpeechRecognitionTaskDelegate 的委托(delegate)方法来检查完成的结果。 func speechRec
我是一名优秀的程序员,十分优秀!