IT TIP

이 작업을 수행 할 수없는 이유 : dynamic x = new ExpandoObject {Foo = 12, Bar = "twelve"}

itqueen 2020. 12. 4. 21:38
반응형

이 작업을 수행 할 수없는 이유 : dynamic x = new ExpandoObject {Foo = 12, Bar = "twelve"}


내가 뭔가 잘못했거나 다음 코드가 실제로 불가능합니까?

dynamic x = new ExpandoObject { Foo = 12, Bar = "twelve" };

이것이 정말로 가능하지 않다면 두 개의 속성으로 ExpandoObject를 인스턴스화하는 또 다른 한 줄 방법이 있습니까?

C # 팀이 일반 객체, 익명 객체 및 열거 형 / 목록과 동일한 초기화 구문을 허용하지 않는 이유는 무엇입니까?

최신 정보

펄 애호가에게 C #의 멋진 새 동적 기능을 보여 주려고했기 때문에이 질문을했지만, .NET Framework의 논리적 인스턴스화라고 생각하는 작업을 수행 할 수 없어서 멈췄습니다 ExpandoObject. Hans Passant의 답변 덕분 ExpandoObject에 이것이 작업에 잘못된 도구 라는 것을 깨달았 습니다. 내 진짜 목표는 C #의 동적 기능을 사용하여 메서드에서 두 개의 명명 된 값을 반환하는 것이 었습니다. Hans가 지적했듯이 dynamic키워드는 이것에 완벽합니다. 나는 필요하지 않은 ExpandoObject이 작업을 수행하기 위해, 모든 오버 헤드.

따라서 메서드에서 명명 된 값 쌍을 반환하고 싶고 형식 안전성, Intellisense, 리팩토링 또는 성능에 대해 걱정하지 않는 경우 다음과 같이 매우 잘 작동합니다.

public dynamic CreateFooBar()
{
    return new { Foo = 42, Bar = "Hello" };
}

용법:

dynamic fooBar = CreateFooBar();
var foo = fooBar.Foo;
var bar = fooBar.Bar;

내가 뭔가 잘못했거나 다음 코드가 실제로 불가능합니까?

정말 불가능합니다. 할당 연산자의 왼쪽에있는 것은 컴파일 타임에 알려진 속성 또는 필드 여야하며, 확장 객체의 경우는 분명히 그렇지 않습니다.

C # 팀이 일반 객체, 익명 객체 및 열거 형 / 목록과 동일한 초기화 구문을 허용하지 않는 이유는 무엇입니까?

질문을 표현하는 방식은 논리적 오류를 나타냅니다. 기능은 기본적으로 구현되지 않으며, 우리는 그것이 나쁜 생각이라고 생각하기 때문에 거의 모든 기능을 허용하지 않습니다! 기능은 기본적으로 구현되지 않으며 작동하려면 구현 해야합니다.

모든 기능을 구현하는 첫 번째 단계는 누군가가 처음부터이를 생각해야한다는 것입니다. 내가 아는 한, 우리는 그렇게하지 않았습니다. 특히 2006 년에 객체 이니셜 라이저를 설계하는 사람이 2010 년에 언어에 "동적"을 추가하고 그에 따라 기능을 설계 할 것이라는 사실을 아는 것은 상당히 어려웠을 것입니다. 기능은 항상 시간을 거꾸로 하지 않고 시간을 앞당기는 디자이너가 설계합니다 . 우리는 미래가 아닌 과거 만 기억합니다.

어쨌든 좋은 생각이라 공유 해주셔서 감사합니다. 누군가가 그것을 생각 했으므로, 우리는 제한된 예산을 사용할 수있는 최선의 아이디어인지 결정하고, 설계하고, 사양을 작성하고, 구현하고, 테스트하고, 문서화하는 등 다음 단계를 진행할 수 있습니다. 고객에게 배송합니다.

조만간 그런 일이 일어나지 않을 것입니다. 지난주 Build에서 발표 한 비동기 및 WinRT 비즈니스 전체로 인해 약간 바쁩니다.


ExpandoObject보다 더 나은 마우스 트랩이 있습니다. 동적 키워드 핸들 침착 익명 유형 :

class Program {      
    static void Main(string[] args) {
        dynamic x = new { Foo = 12, Bar = "twelve" };
        Display(x);
    }
    static void Display(dynamic x) {
        Console.WriteLine(x.Foo);
        Console.WriteLine(x.Bar);
    }
}

한 가지 불행한 문제는 C # 컴파일러가 멤버에게 내부 접근성 만 제공하는 익명 형식을 생성한다는 것 입니다. 즉, 다른 어셈블리의 멤버에 액세스하려고 할 때 런타임 오류가 발생합니다. Bummer.

C # v7에서 훨씬 향상된 튜플을 고려하십시오 .


Dynamitey (오픈 소스 PCL 및 nuget에 있음)에는 인라인이 가능한 확장초기화 하는 구문 이 있습니다.

 //using Dynamitey.DynamicObjects
 var x = Build<ExpandoObject>.NewObject(Foo:12, Bar:"twelve");

나를 위해 일한 한 가지 해결 ToExpando()방법은 Yan Cui ( source )의 확장 방법입니다 .

public static class DictionaryExtensionMethods
{
    /// <summary>
    /// Extension method that turns a dictionary of string and object to an ExpandoObject
    /// </summary>
    public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary)
    {
        var expando = new ExpandoObject();
        var expandoDic = (IDictionary<string, object>) expando;

        // go through the items in the dictionary and copy over the key value pairs)
        foreach (var kvp in dictionary)
        {
            // if the value can also be turned into an ExpandoObject, then do it!
            if (kvp.Value is IDictionary<string, object>)
            {
                var expandoValue = ((IDictionary<string, object>) kvp.Value).ToExpando();
                expandoDic.Add(kvp.Key, expandoValue);
            }
            else if (kvp.Value is ICollection)
            {
                // iterate through the collection and convert any strin-object dictionaries
                // along the way into expando objects
                var itemList = new List<object>();
                foreach (var item in (ICollection) kvp.Value)
                {
                    if (item is IDictionary<string, object>)
                    {
                        var expandoItem = ((IDictionary<string, object>) item).ToExpando();
                        itemList.Add(expandoItem);
                    }
                    else
                    {
                        itemList.Add(item);
                    }
                }

                expandoDic.Add(kvp.Key, itemList);
            }
            else
            {
                expandoDic.Add(kvp);
            }
        }

        return expando;
    }
}

사용 예 :

public const string XEntry = "ifXEntry";
public static readonly dynamic XEntryItems = new Dictionary<string, object>
{
    { "Name",                     XEntry + ".1" },
    { "InMulticastPkts",          XEntry + ".2" },
    { "InBroadcastPkts",          XEntry + ".3" },
    { "OutMulticastPkts",         XEntry + ".4" },
    { "OutBroadcastPkts",         XEntry + ".5" },
    { "HCInOctets",               XEntry + ".6" },
    { "HCInUcastPkts",            XEntry + ".7" },
    { "HCInMulticastPkts",        XEntry + ".8" },
    { "HCInBroadcastPkts",        XEntry + ".9" },
    { "HCOutOctets",              XEntry + ".10" },
    { "HCOutUcastPkts",           XEntry + ".11" },
    { "HCOutMulticastPkts",       XEntry + ".12" },
    { "HCOutBroadcastPkts",       XEntry + ".13" },
    { "LinkUpDownTrapEnable",     XEntry + ".14" },
    { "HighSpeed",                XEntry + ".15" },
    { "PromiscuousMode",          XEntry + ".16" },
    { "ConnectorPresent",         XEntry + ".17" },
    { "Alias",                    XEntry + ".18" },
    { "CounterDiscontinuityTime", XEntry + ".19" },
}.ToExpando();

그런 다음 XEntryItems.Name.

추신 : ExpandoObjects에서 개체 이니셜 라이저를 지원하려면 여기 에서 투표 하십시오 .


get 및 setter가있는 속성이 이미 있기 때문에 이러한 종류의 초기화 구문이 가능합니다. expando 개체에는 아직 내가 말할 수있는 속성이 없습니다.


이 작업을 수행하는 훨씬 더 간단한 방법 :

Func<Dictionary<string, object>, ExpandoObject> parse = dict =>
{
    var expando = new ExpandoObject();
    foreach (KeyValuePair<string, object> entry in dict)
    {
        expando.Add(entry.Key, entry.Value);
    }
    return expando;
};

그런 다음 구문 분석 함수를 호출하고 사전에 매개 변수로 전달하면됩니다. 물론 이것은 함수 대신 메서드로 구현할 수 있습니다.

참고 URL : https://stackoverflow.com/questions/7478048/why-cant-i-do-this-dynamic-x-new-expandoobject-foo-12-bar-twelve

반응형