c# - 在运行时动态添加 C# 属性

标签 c# dynamic reflection properties

我知道有一些问题可以解决这个问题,但答案通常遵循推荐字典或参数集合的思路,这在我的情况下不起作用。

我正在使用一个库,该库通过反射对具有属性的对象做很多巧妙的事情。这适用于定义的类以及动态类。我需要更进一步,按照这些思路做一些事情:

public static object GetDynamicObject(Dictionary<string,object> properties) {
    var myObject = new object();
    foreach (var property in properties) {
        //This next line obviously doesn't work... 
        myObject.AddProperty(property.Key,property.Value);
    }
    return myObject;
}

public void Main() {
    var properties = new Dictionary<string,object>();
    properties.Add("Property1",aCustomClassInstance);
    properties.Add("Property2","TestString2");

    var myObject = GetDynamicObject(properties);

    //Then use them like this (or rather the plug in uses them through reflection)
    var customClass = myObject.Property1;
    var myString = myObject.Property2;

}

该库适用于动态变量类型,具有手动分配的属性。但是我不知道事先会添加多少或哪些属性。

最佳答案

您看过 ExpandoObject 了吗?

参见:https://learn.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject

来自 MSDN:

The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject.sampleMember instead of more complex syntax like sampleObject.GetAttribute("sampleMember").

允许您做一些很酷的事情,例如:

dynamic dynObject = new ExpandoObject();
dynObject.SomeDynamicProperty = "Hello!";
dynObject.SomeDynamicAction = (msg) =>
    {
        Console.WriteLine(msg);
    };

dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);

根据您的实际代码,您可能更感兴趣:

public static dynamic GetDynamicObject(Dictionary<string, object> properties)
{
    return new MyDynObject(properties);
}

public sealed class MyDynObject : DynamicObject
{
    private readonly Dictionary<string, object> _properties;

    public MyDynObject(Dictionary<string, object> properties)
    {
        _properties = properties;
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return _properties.Keys;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (_properties.ContainsKey(binder.Name))
        {
            result = _properties[binder.Name];
            return true;
        }
        else
        {
            result = null;
            return false;
        }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (_properties.ContainsKey(binder.Name))
        {
            _properties[binder.Name] = value;
            return true;
        }
        else
        {
            return false;
        }
    }
}

这样你只需要:

var dyn = GetDynamicObject(new Dictionary<string, object>()
    {
        {"prop1", 12},
    });

Console.WriteLine(dyn.prop1);
dyn.prop1 = 150;

从 DynamicObject 派生允许您想出自己的策略来处理这些动态成员请求,当心这里有怪物:编译器将无法验证很多动态调用都不会获得智能感知,所以请牢记这一点。

关于c# - 在运行时动态添加 C# 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15819720/

相关文章:

c# - 如何在 MVC Controller 中使用消息框?

php - 以动态方式为函数提供参数

当在派生类中定义重载时,C# 后期绑定(bind)方法重载不起作用

c# - 用于像 Wireshark Diagnostics 这样的窗口的 XAML?

c# - 将通用事件处理程序连接到同一类型的多个控件

c# - 无法通过 TCP/Sockets .net 退出具有多个缓冲区传输的循环

c# - 有没有办法在 C# 中获取对调用对象的引用?

javascript - optionHTML 和 innerHTML 覆盖 `<option>` 占位符

java - 如何使用反射获取以 List<SomeObject> 作为参数的方法

php反射获取属性而不获取基类的属性