런타임에 동적으로 C # 속성 추가


89

이 문제를 해결하는 몇 가지 질문이 있다는 것을 알고 있지만 대답은 일반적으로 내 상황에서 작동하지 않는 사전 또는 매개 변수 모음을 권장하는 줄을 따릅니다.

반사를 통해 작동하는 라이브러리를 사용하여 속성이있는 개체로 많은 영리한 작업을 수행하고 있습니다. 이것은 동적 클래스뿐만 아니라 정의 된 클래스에서도 작동합니다. 한 단계 더 나아가 다음과 같은 작업을 수행해야합니다.

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;

}

라이브러리는 속성이 수동으로 할당 된 동적 변수 유형에서 잘 작동합니다. 그러나 사전에 얼마나 많은 속성이 추가되는지 알 수 없습니다.

답변:


105

ExpandoObject를 살펴 보셨습니까?

보다: http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx

MSDN에서 :

ExpandoObject 클래스를 사용하면 런타임에 인스턴스의 멤버를 추가 및 삭제할 수 있으며 이러한 멤버의 값을 설정하고 가져올 수도 있습니다. 이 클래스는 동적 바인딩을 지원하므로 sampleObject.GetAttribute ( "sampleMember")와 같은 더 복잡한 구문 대신 sampleObject.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에서 파생하면, 이러한 동적 구성원의 요청을 처리하기위한 자신의 전략을 마련 할 수 있습니다 : 여기가 조심 몬스터를 컴파일러가됩니다 없습니다 동적 호출을 많이 확인할 수 당신은 IntelliSense를 얻을 수 없습니다, 그래서 그냥 계속 염두에 두십시오.


40

훌륭한 답변에 대해 @Clint에게 감사드립니다.

Expando Object를 사용하여이 문제를 얼마나 쉽게 해결할 수 있는지 강조하고 싶었습니다.

    var dynamicObject = new ExpandoObject() as IDictionary<string, Object>;
    foreach (var property in properties) {
        dynamicObject.Add(property.Key,property.Value);
    }

4

json 문자열을 사전으로 역 직렬화 한 다음 새 속성을 추가 한 다음 직렬화 할 수 있습니다.

 var jsonString = @"{}";

        var jsonDoc = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);

        jsonDoc.Add("Name", "Khurshid Ali");

        Console.WriteLine(JsonSerializer.Serialize(jsonDoc));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.