কীভাবে নতুন বেনাম শ্রেণীর গতিশীল?


95

সি # 3.0 এ আপনি নিম্নলিখিত সিনট্যাক্স সহ বেনাম শ্রেণি তৈরি করতে পারেন

var o1 = new { Id = 1, Name = "Foo" };

এই ছদ্মবেশী বেনিয়াকে কোনও চলকটিতে গতিশীল করার কোনও উপায় আছে কি?


উদাহরণ:

var o1 = new { Id = 1, Name = "Foo" };
var o2 = new { SQ = 2, Birth = DateTime.Now };

গতিশীল তৈরি উদাহরণ:

var o1 = DynamicNewAnonymous(new NameValuePair("Id", 1), new NameValuePair("Name", "Foo"));
var o2 = DynamicNewAnonymous(new NameValuePair("SQ", 2), new NameValuePair("Birth", 
DateTime.Now));

বীচুস আমার করা দরকার:

dynamic o1 = new ExpandObject(); 
o1."ID" = 1;    <--"ID" is dynamic name
o1."Name" = "Foo";  <--"Name" is dynamic name

এবং দৃশ্য 1:

void ShowPropertiesValue(object o)
{
  Type oType = o.GetType();
  foreach(var pi in oType.GetProperties())
  {
    Console.WriteLine("{0}={1}", pi.Name, pi.GetValue(o, null));
  }
}

যদি আমি কল করি:

dynamic o1 = new ExpandObject();
o1.Name = "123";
ShowPropertiesValue(o1);

এটি ফলাফলটি প্রদর্শন করতে পারে না:

Name = 123

এবং আমি কীভাবে এক্সপ্ল্যান্ডোঅবজেক্টকে অনামহাউসটাইপ রূপান্তর করব?

Type type = o1.GetType();
type.GetProperties();   <--I hope it can get all property of o1

সর্বশেষে, আমি শোপ্রোপার্টিভ্যালু () পদ্ধতিটি সংশোধন করি

void ShowPropertiesValue(object o)
{
  if( o is static object ) <--How to check it is dynamic or static object?
  {
    Type oType = o.GetType();
    foreach(var pi in oType.GetProperties())
    {
      Console.WriteLine("{0}={1}", pi.Name, pi.GetValue(o, null));
    }
  }
  else if( o is dynamic object )  <--How to check it is dynamic or static object?
  {
    foreach(var pi in ??? )  <--How to get common dynamic object's properties info ?
    {
      Console.WriteLine("{0}={1}", pi.Name, pi.GetValue(o, null));
    } 
  }
}

ডায়নামিকনিউনামনিম পদ্ধতি কীভাবে কার্যকর করবেন বা কীভাবে শোপ্রোপার্টিভ্যালিয়াকে পরিবর্তন করবেন?

আমার অনুপ্রেরণা হ'ল:

dynamic o1 = new MyDynamic();
o1.Name = "abc";
Type o1Type = o1.GetType();
var props = o1Type.GetProperties(); <--I hope can get the Name Property

যদি আমি ডায়নামিকবজেক্টের গেটটাইপ পদ্ধতি হুক করতে পারি এবং জোরালোভাবে টাইপ করা ধরণে রূপান্তর করতে বাধ্য করি। উপরের সীমলেস কোড সূক্ষ্মভাবে কাজ করতে পারে।


@ ভ্ল্যাড: আমি স্বীকার করছি যে অনুপ্রেরণাগুলি সম্পর্কে আমি কিছুটা অস্পষ্ট।
স্টিভেন সুদিত

@ ভ্লাদলাজেরেনকো আমার মনে হয় আপনি ঠিক বলেছেন :-)
ওবরেফ্রাকের

দয়া করে আমাদের বলুন, আপনি কী করতে চান এবং কেন এটি আপনার নির্বাচিত সমাধান।
ওবরেফ্রাক

ExpandoObject, ExpandObject নয় (যুক্ত 'o')।
এন 01: 0

@ স্টিভেনসডিট এই নিবন্ধটি আপনার এক বা অন্যটি ব্যবহারের অনুপ্রেরণা খুঁজে পেতে সহায়তা করতে পারে: ব্লগস.এমএসএনএন
বি

উত্তর:


75

নামবিহীন প্রকারগুলি কেবল নিয়মিত প্রকার যা স্পষ্টভাবে ঘোষণা করা হয়। তাদের সাথে কিছু করার নেই dynamic

এখন, আপনি যদি কোনও ExpandoObject ব্যবহার করেন এবং এটি একটি dynamicভেরিয়েবলের মাধ্যমে উল্লেখ করতে চান তবে আপনি ফ্লাইয়ের ক্ষেত্রগুলি যুক্ত করতে বা সরিয়ে ফেলতে পারেন।

সম্পাদনা করুন

নিশ্চিত যে আপনি এটি করতে পারেন: কেবল এটি এ castালাই IDictionary<string, object>। তারপরে আপনি সূচকটি ব্যবহার করতে পারেন।

ক্ষেত্রগুলির উপর পুনরাবৃত্তি করতে আপনি একই ingালাই কৌশলটি ব্যবহার করেন:

dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;

foreach (var property in (IDictionary<string, object>)employee)
{
    Console.WriteLine(property.Key + ": " + property.Value);
}
// This code example produces the following output:
// Name: John Smith
// Age: 33

উপরের কোড এবং আরও অনেক কিছু সেই লিঙ্কটিতে ক্লিক করে পাওয়া যাবে।


4
তবে ExpandoObject এটি করতে পারে না:dynamic o1 = new ExpandObject(); o1."ID" = 1; o1."Name" = "Foo";
ফ্ল্যাশ করুন

তবে এটিও করতে পারে না: টাইপ করুন o1Type = o1. গেটটাইপ (); var প্রপস = o1Type.GetProperties (); প্রপস খালি
ফ্ল্যাশ

4
আপনি যা করছেন তা বলছেন যে গতিশীল বৈশিষ্ট্যগুলি দৃ strongly়ভাবে টাইপ করা বৈশিষ্ট্যের সাথে অভিন্ন নয়। এটি তুচ্ছ সত্য।
স্টিভেন সুদিত

4
stackoverflow.com/a/4024786/998793 দেখায় কিভাবে একটি জেনেরিক অভিধান কাস্ট করে এই কাজ করতে: ((IDictionary<string, object>)o1).Add("Name", "Foo");। তারপরে আপনি এই হিসাবে অ্যাক্সেস করতে পারবেনo1.Name
রোজারিলিটো

15

আপনি এর মতো একটি এক্সপেন্ডোঅবজেক্ট তৈরি করতে পারেন:

IDictionary<string,object> expando = new ExpandoObject();
expando["Name"] = value;

এবং এটিকে গতিশীল করার পরে, সেই মানগুলি বৈশিষ্ট্যের মতো দেখাবে:

dynamic d = expando;
Console.WriteLine(d.Name);

তবে এগুলি প্রকৃত বৈশিষ্ট্য নয় এবং প্রতিবিম্ব ব্যবহার করে অ্যাক্সেস করা যায় না। সুতরাং নিম্নলিখিত বিবৃতি একটি শূন্য ফিরে আসবে:

d.GetType().GetProperty("Name") 

2

কারণে শীতল ExpandoObject ক্লাস ব্যবহার করে গতিশীল ক্লাস তৈরি করা সম্ভব। তবে সম্প্রতি আমি প্রকল্পে কাজ করেছি এবং মুখোমুখি হয়েছি যে এক্সপ্ল্যান্ডো অবজেক্টটি এক অনামান্য শ্রেণীর হিসাবে এক্সএমএলে একই বিন্যাসে সেরালাইজ করা হয়েছে, এটি করুণা ছিল (= এজন্যই আমি নিজের শ্রেণি তৈরি করে আপনার সাথে ভাগ করে নেওয়ার সিদ্ধান্ত নিয়েছি using এটি ব্যবহার করছে প্রতিবিম্ব এবং গতিশীল দিকনির্দেশনা, সমাবেশ, শ্রেণি এবং তাত্পর্য সত্যই গতিশীলভাবে তৈরি করে fly

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using static YourNamespace.DynamicTypeBuilderTest;

namespace YourNamespace
{

    /// This class builds Dynamic Anonymous Classes

    public class DynamicTypeBuilderTest
    {    
        ///   
        /// Create instance based on any Source class as example based on PersonalData
        ///
        public static object CreateAnonymousDynamicInstance(PersonalData personalData, Type dynamicType, List<ClassDescriptorKeyValue> classDescriptionList)
        {
            var obj = Activator.CreateInstance(dynamicType);

            var propInfos = dynamicType.GetProperties();

            classDescriptionList.ForEach(x => SetValueToProperty(obj, propInfos, personalData, x));

            return obj;
        }

        private static void SetValueToProperty(object obj, PropertyInfo[] propInfos, PersonalData aisMessage, ClassDescriptorKeyValue description)
        {
            propInfos.SingleOrDefault(x => x.Name == description.Name)?.SetValue(obj, description.ValueGetter(aisMessage), null);
        }

        public static dynamic CreateAnonymousDynamicType(string entityName, List<ClassDescriptorKeyValue> classDescriptionList)
        {
            AssemblyName asmName = new AssemblyName();
            asmName.Name = $"{entityName}Assembly";
            AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndCollect);

            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule($"{asmName.Name}Module");

            TypeBuilder typeBuilder = moduleBuilder.DefineType($"{entityName}Dynamic", TypeAttributes.Public);

            classDescriptionList.ForEach(x => CreateDynamicProperty(typeBuilder, x));

            return typeBuilder.CreateTypeInfo().AsType();
        }

        private static void CreateDynamicProperty(TypeBuilder typeBuilder, ClassDescriptorKeyValue description)
        {
            CreateDynamicProperty(typeBuilder, description.Name, description.Type);
        }

        ///
        ///Creation Dynamic property (from MSDN) with some Magic
        ///
        public static void CreateDynamicProperty(TypeBuilder typeBuilder, string name, Type propType)
        {
            FieldBuilder fieldBuider = typeBuilder.DefineField($"{name.ToLower()}Field",
                                                            propType,
                                                            FieldAttributes.Private);

            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(name,
                                                             PropertyAttributes.HasDefault,
                                                             propType,
                                                             null);

            MethodAttributes getSetAttr =
                MethodAttributes.Public | MethodAttributes.SpecialName |
                    MethodAttributes.HideBySig;

            MethodBuilder methodGetBuilder =
                typeBuilder.DefineMethod($"get_{name}",
                                           getSetAttr,
                                           propType,
                                           Type.EmptyTypes);

            ILGenerator methodGetIL = methodGetBuilder.GetILGenerator();

            methodGetIL.Emit(OpCodes.Ldarg_0);
            methodGetIL.Emit(OpCodes.Ldfld, fieldBuider);
            methodGetIL.Emit(OpCodes.Ret);

            MethodBuilder methodSetBuilder =
                typeBuilder.DefineMethod($"set_{name}",
                                           getSetAttr,
                                           null,
                                           new Type[] { propType });

            ILGenerator methodSetIL = methodSetBuilder.GetILGenerator();

            methodSetIL.Emit(OpCodes.Ldarg_0);
            methodSetIL.Emit(OpCodes.Ldarg_1);
            methodSetIL.Emit(OpCodes.Stfld, fieldBuider);
            methodSetIL.Emit(OpCodes.Ret);

            propertyBuilder.SetGetMethod(methodGetBuilder);
            propertyBuilder.SetSetMethod(methodSetBuilder);

        }

        public class ClassDescriptorKeyValue
        {
            public ClassDescriptorKeyValue(string name, Type type, Func<PersonalData, object> valueGetter)
            {
                Name = name;
                ValueGetter = valueGetter;
                Type = type;
            }

            public string Name;
            public Type Type;
            public Func<PersonalData, object> ValueGetter;
        }

        ///
        ///Your Custom class description based on any source class for example
        /// PersonalData
        public static IEnumerable<ClassDescriptorKeyValue> GetAnonymousClassDescription(bool includeAddress, bool includeFacebook)
        {
            yield return new ClassDescriptorKeyValue("Id", typeof(string), x => x.Id);
            yield return new ClassDescriptorKeyValue("Name", typeof(string), x => x.FirstName);
            yield return new ClassDescriptorKeyValue("Surname", typeof(string), x => x.LastName);
            yield return new ClassDescriptorKeyValue("Country", typeof(string), x => x.Country);
            yield return new ClassDescriptorKeyValue("Age", typeof(int?), x => x.Age);
            yield return new ClassDescriptorKeyValue("IsChild", typeof(bool), x => x.Age < 21);

            if (includeAddress)
                yield return new ClassDescriptorKeyValue("Address", typeof(string), x => x?.Contacts["Address"]);
            if (includeFacebook)
                yield return new ClassDescriptorKeyValue("Facebook", typeof(string), x => x?.Contacts["Facebook"]);
        }

        ///
        ///Source Data Class for example
        /// of cause you can use any other class
        public class PersonalData
        { 
            public int Id { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string Country { get; set; }
            public int Age { get; set; }

            public Dictionary<string, string> Contacts { get; set; }
        }

    }
}

ডায়নামিক টাইপবিল্ডার ব্যবহার করা খুব সহজ, আপনার কেবল কয়েকটি লাইন লাগাতে হবে:

    public class ExampleOfUse
    {
        private readonly bool includeAddress;
        private readonly bool includeFacebook;
        private readonly dynamic dynamicType;
        private readonly List<ClassDescriptorKeyValue> classDiscriptionList;
        public ExampleOfUse(bool includeAddress = false, bool includeFacebook = false)
        {
            this.includeAddress = includeAddress;
            this.includeFacebook = includeFacebook;
            this.classDiscriptionList = DynamicTypeBuilderTest.GetAnonymousClassDescription(includeAddress, includeFacebook).ToList();
            this.dynamicType = DynamicTypeBuilderTest.CreateAnonymousDynamicType("VeryPrivateData", this.classDiscriptionList);
        }

        public object Map(PersonalData privateInfo)
        {
            object dynamicObject = DynamicTypeBuilderTest.CreateAnonymousDynamicInstance(privateInfo, this.dynamicType, classDiscriptionList);

            return dynamicObject;
        }

    }

আমি আশা করি যে এই কোড স্নিপেটটি কারওকে সহায়তা করবে =) উপভোগ করুন!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.