简体   繁体   English

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

[英]How to set the property value using reflection in C# when the property is a delegate type?

I have a property in a dll that i am using using Reflection feature in C#. 我在C#中使用反射功能的dll中有一个属性。 I would like to set the property and the property type is a delegate type. 我想设置属性,并且属性类型是委托类型。

Please let me know the steps involved in setting the property using the Reflection. 请让我知道使用反射设置属性的步骤。

I know that SetValue method need to be used to do this, but don't know how to set the property of the delegate type. 我知道需要使用SetValue方法来执行此操作,但不知道如何设置委托类型的属性。

SetValue(objectName, 1, null) is to set an integer property using reflection, but don't know how to set the property of the delegate type. SetValue(objectName,1,null)用于使用反射设置整数属性,但不知道如何设置委托类型的属性。

How to declare a variable of the delegate property type and initialize it using reflection? 如何声明委托属性类型的变量并使用反射对其进行初始化?

It is rather straightforward 这很简单

Given a class with a delegate property such as 给定具有委托属性的类,例如

class A
{
    public Action Action { get; set; }
}

we can set it via reflection like so 我们可以像这样通过反射来设置

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

Note that we have to cast a lambda expression to a delegate type, here System.Action because there is no type inference context but that is an unimportant, it is just one of many ways to obtain a value of a delegate type. 请注意,我们必须将lambda表达式转换为委托类型,在这里为System.Action因为没有类型推断上下文,但这并不重要,它只是获得委托类型值的许多方法之一。

That does lead us to the second part of your question however: 但这确实将我们引到您的问题的第二部分:

How to declare a variable of the delegate property type and initialize it using reflection? 如何声明委托属性类型的变量并使用反射对其进行初始化?

We need to create a delegate value of a type matching the declared property. 我们需要创建与声明的属性匹配的类型的委托值。 In this case the property was System.Action . 在这种情况下,属性为System.Action

At the simplest level you set it the same way you set the int property: 在最简单的级别上,可以使用设置int属性的相同方式进行设置:

Assuming this class: 假设此类:

public class MyClass
{
    internal Action<object> Simple { get; set; }
}

Setting the property: 设置属性:

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

If the delegate contains a type that is not public as an argument, you can still set it using object, depending on covariance/contravariance. 如果委托包含的参数类型不是公共的,则仍可以使用对象来设置它,具体取决于协方差/相反方差。

Assuming the class is as below, setting the property with Action<object> still works 假设该类如下,仍然可以使用Action<object>设置属性

public class MyClass
{
    internal Action<Arg> Simple { get; set; }
}
internal class Arg { }

If the delegate type itself is internal you need to create an instance of that internal delegate type: 如果委托类型本身是内部的,则需要创建该内部委托类型的实例:

Assuming: 假设:

public class MyClass
{
    internal Internal Simple { get; set; }
}
internal class Arg { }

internal delegate void Internal(Arg arg);

You can use: 您可以使用:

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

Note: The above code works, because we created a delegate ( Action<object> ) that can be compatible with the Internal delegate (the arguments do not need any explicit casting) and used the methodInfo of that delegate to create out new internal delegate. 注意:上面的代码行得通,因为我们创建了一个可以与Internal委托兼容的委托( Action<object> )(参数不需要任何显式强制转换),并使用该委托的methodInfo来创建新的内部委托。 depending on the type of the delegate you want to create this may be trickier, but without more info, this is example should be a good starting point. 根据您要创建的委托人的类型,这可能会比较棘手,但是如果没有更多信息,则此示例应该是一个很好的起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM