我在一个dll中有一个属性,我在C#中使用反射功能。我想设置属性,属性类型是委托类型。
请告诉我使用反射设置属性所涉及的步骤。
我知道需要使用SetValue方法来执行此操作,但不知道如何设置委托类型的属性。
SetValue(objectName,1,null)是使用反射设置整数属性,但不知道如何设置委托类型的属性。
如何声明委托属性类型的变量并使用反射初始化它?
答案 0 :(得分:2)
这很简单
给定一个具有委托属性的类,例如
class A
{
public Action Action { get; set; }
}
我们可以通过反射来设置它
void Main()
{
var a = new A();
var type = a.GetType();
var delegateProperty = type.GetProperty(nameof(A.Action));
delegateProperty.SetValue(a, (Action)(() => Console.WriteLine("via reflection")));
a.Action();
}
请注意,我们必须将lambda表达式转换为委托类型,此处为System.Action
,因为没有类型推断上下文但这不重要,它只是获取委托值的众多方法之一类型。
然而,这确实引导了我们问题的第二部分:
如何声明委托属性类型的变量并初始化 它使用反射?
我们需要创建与声明的属性匹配的类型的委托值。在这种情况下,该属性为System.Action
。
答案 1 :(得分:1)
在最简单的级别,您设置它的方式与设置int
属性的方式相同:
假设这个课程:
public class MyClass
{
internal Action<object> Simple { get; set; }
}
设置属性:
var type = typeof(MyClass);
var action = new Action<object>((o) => Console.WriteLine("Invoked with {0}", o));
var obj = new MyClass();
type.GetProperty("Simple", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(obj, action);
如果委托包含一个非公开作为参数的类型,您仍然可以使用object设置它,具体取决于协方差/逆变。
假设该类如下所示,设置Action<object>
的属性仍然有效
public class MyClass
{
internal Action<Arg> Simple { get; set; }
}
internal class Arg { }
如果委托类型本身是内部的,则需要创建该内部委托类型的实例:
假设:
public class MyClass
{
internal Internal Simple { get; set; }
}
internal class Arg { }
internal delegate void Internal(Arg arg);
您可以使用:
var type = typeof(MyClass);
var prop = type.GetProperty("Simple", BindingFlags.NonPublic | BindingFlags.Instance);
var action = new Action<object>((o) => Console.WriteLine("Invoked with {0}", o));
var delegateInsrtance = Delegate.CreateDelegate(prop.PropertyType, action.Target, action.Method);
var obj = new MyClass();
prop.SetValue(obj, delegateInsrtance);
注意:以上代码有效,因为我们创建了一个可以与Action<object>
委托兼容的委托(Internal
)(参数不需要任何显式转换并使用该委托的methodInfo创建新的内部委托。根据你想要创建的委托的类型,这可能会更棘手,但没有更多的信息,这个例子应该是一个很好的起点。