如何使用动态找出何时使用 属性?
How can I use a dynamic to find out when a property is used?
我想找出某个方法使用了源输入对象中的哪些属性。执行该方法后,我需要在数据库中存储使用了哪些属性。
输入可以是任何具有简单类型的 class,如下所示:
public class MyData : IMyData
{
public string A { get; set; }
public int B { get; set; }
public decimal C { get; set; }
}
我认为可以使用接口作为方法的输入来完成,因此我可以用更高级的对象替换原始对象,该对象存储属性的用法
public interface IMyData
{
string A { get; }
int B { get; }
decimal C { get; }
}
那我可以
- 创建具有相同属性的动态对象
- 使用ImpromptuInterface模拟动态对象实现我的接口
用这个动态接口调用我的方法
private static void Main()
{
var data = new MyData { A = "Test", B = 3, C = new decimal(1.2) };
IDictionary<string, object> replacementObject = new ExpandoObject();
replacementObject.Add("FieldsUsed", new List<string>());
foreach (var property in data.GetType().GetProperties())
replacementObject.Add(property.Name, property.GetValue(data));
var replacementInterface = replacementObject.ActLike<IMyData>();
DoStuff(replacementInterface);
Console.WriteLine($"The method used these fields {string.Join(", ", (List<string>)replacementObject["FieldsUsed"])}");
}
private static void DoStuff(IMyData source)
{
Console.WriteLine($"A is {source.A}");
if (source.B > 5)
Console.WriteLine($"C is {source.C}");
}
在上面的示例中,我想存储字段 A 和 B 已被使用。
当我的 DoStuff 方法使用 属性 时,只有我不知道应该如何存储。
如果您想知道何时使用 属性,像 INotifyPropertyChanged 这样的接口可以在运行时为您完成。这个例子只是关于写入通知(实际上改变了一个值),但是将它扩展到读取和写入是微不足道的。这当然不是一件完美的事情,因为不同的执行可能遵循使用不同属性的不同代码路径。
如果函数采用特定类型作为输入,您必须假设所有属性都可能相关。对于抽象类型和接口尤其如此——通常接口 exists 这个函数。如果它是这两者之一,您也可以始终提供自己对这些接口和抽象的实现 class.
我无法摆脱这是一个 XY 问题的感觉。
你可以这样写一个包装器:
public class ClassWrapper<T>: DynamicObject where T:class
{
private readonly T _obj;
private readonly List<string> _fieldsUsed=new List<string>();
public ClassWrapper(T obj)
{
_obj = obj;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
PropertyInfo propertyInfo = _obj.GetType().GetProperty(binder.Name);
_fieldsUsed.Add(binder.Name);
result = propertyInfo.GetValue(_obj);
return true;
}
public List<string> GetFieldsUsed() => _fieldsUsed;
public T GetWrapper()
{
return this.ActLike<T>();
}
}
并像
一样使用它
var data = new MyData { A = "Test", B = 3, C = new decimal(1.2) };
var mc=new ClassWrapper<IMyData>(data);
IMyData wrapped = mc.GetWrapper();
DoStuff(wrapped);
Console.WriteLine($"The method used these fields {string.Join(", ", (List<string>)mc.GetFieldsUsed())}");
我想找出某个方法使用了源输入对象中的哪些属性。执行该方法后,我需要在数据库中存储使用了哪些属性。
输入可以是任何具有简单类型的 class,如下所示:
public class MyData : IMyData
{
public string A { get; set; }
public int B { get; set; }
public decimal C { get; set; }
}
我认为可以使用接口作为方法的输入来完成,因此我可以用更高级的对象替换原始对象,该对象存储属性的用法
public interface IMyData
{
string A { get; }
int B { get; }
decimal C { get; }
}
那我可以
- 创建具有相同属性的动态对象
- 使用ImpromptuInterface模拟动态对象实现我的接口
用这个动态接口调用我的方法
private static void Main() { var data = new MyData { A = "Test", B = 3, C = new decimal(1.2) }; IDictionary<string, object> replacementObject = new ExpandoObject(); replacementObject.Add("FieldsUsed", new List<string>()); foreach (var property in data.GetType().GetProperties()) replacementObject.Add(property.Name, property.GetValue(data)); var replacementInterface = replacementObject.ActLike<IMyData>(); DoStuff(replacementInterface); Console.WriteLine($"The method used these fields {string.Join(", ", (List<string>)replacementObject["FieldsUsed"])}"); } private static void DoStuff(IMyData source) { Console.WriteLine($"A is {source.A}"); if (source.B > 5) Console.WriteLine($"C is {source.C}"); }
在上面的示例中,我想存储字段 A 和 B 已被使用。
当我的 DoStuff 方法使用 属性 时,只有我不知道应该如何存储。
如果您想知道何时使用 属性,像 INotifyPropertyChanged 这样的接口可以在运行时为您完成。这个例子只是关于写入通知(实际上改变了一个值),但是将它扩展到读取和写入是微不足道的。这当然不是一件完美的事情,因为不同的执行可能遵循使用不同属性的不同代码路径。
如果函数采用特定类型作为输入,您必须假设所有属性都可能相关。对于抽象类型和接口尤其如此——通常接口 exists 这个函数。如果它是这两者之一,您也可以始终提供自己对这些接口和抽象的实现 class.
我无法摆脱这是一个 XY 问题的感觉。
你可以这样写一个包装器:
public class ClassWrapper<T>: DynamicObject where T:class
{
private readonly T _obj;
private readonly List<string> _fieldsUsed=new List<string>();
public ClassWrapper(T obj)
{
_obj = obj;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
PropertyInfo propertyInfo = _obj.GetType().GetProperty(binder.Name);
_fieldsUsed.Add(binder.Name);
result = propertyInfo.GetValue(_obj);
return true;
}
public List<string> GetFieldsUsed() => _fieldsUsed;
public T GetWrapper()
{
return this.ActLike<T>();
}
}
并像
一样使用它 var data = new MyData { A = "Test", B = 3, C = new decimal(1.2) };
var mc=new ClassWrapper<IMyData>(data);
IMyData wrapped = mc.GetWrapper();
DoStuff(wrapped);
Console.WriteLine($"The method used these fields {string.Join(", ", (List<string>)mc.GetFieldsUsed())}");