当属性是委托类型时,如何使用C#中的反射设置属性值?

时间:2017-11-27 07:00:15

标签: c# reflection properties delegates

我在一个dll中有一个属性,我在C#中使用反射功能。我想设置属性,属性类型是委托类型。

请告诉我使用反射设置属性所涉及的步骤。

我知道需要使用SetValue方法来执行此操作,但不知道如何设置委托类型的属性。

SetValue(objectName,1,null)是使用反射设置整数属性,但不知道如何设置委托类型的属性。

如何声明委托属性类型的变量并使用反射初始化它?

2 个答案:

答案 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创建新的内部委托。根据你想要创建的委托的类型,这可能会更棘手,但没有更多的信息,这个例子应该是一个很好的起点。