【问题标题】:How to set the property value using reflection in C# when the property is a delegate type?当属性是委托类型时,如何在 C# 中使用反射设置属性值?
【发布时间】:2018-05-10 08:48:57
【问题描述】:

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

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

我知道需要使用SetValue方法来做这个,但是不知道如何设置委托类型的属性。

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

如何声明一个delegate属性类型的变量并使用反射进行初始化?

【问题讨论】:

  • 你想设置/添加一个事件吗?例如。 Button.Click?

标签: c# reflection properties delegates


【解决方案1】:

比较简单

给定一个具有委托属性的类,例如

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

【讨论】:

    【解决方案2】:

    在最简单的级别上,您设置它的方式与设置 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);
    

    如果委托包含不作为参数公开的类型,您仍然可以使用对象设置它,具体取决于协变/逆变。

    假设类如下,使用Action&lt;object&gt; 设置属性仍然有效

    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);
    

    注意:上述代码有效,因为我们创建了一个可以与Internal 委托兼容的委托(Action&lt;object&gt;)(参数不需要任何显式转换)并使用该委托的方法信息来创建新的内部委托。根据您要创建的委托的类型,这可能会更棘手,但如果没有更多信息,这个示例应该是一个很好的起点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-09
      • 2012-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多