В C # 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
А также я, как преобразовать ExpandoObject в AnonymouseType?
Type type = o1.GetType();
type.GetProperties(); <--I hope it can get all property of o1
Наконец, я изменяю метод ShowPropertiesValue ()
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));
}
}
}
Как реализовать метод DynamicNewAnonymous или как изменить ShowPropertiesValue ()?
Моя мотивация:
dynamic o1 = new MyDynamic();
o1.Name = "abc";
Type o1Type = o1.GetType();
var props = o1Type.GetProperties(); <--I hope can get the Name Property
Если я могу подключить метод GetType для dynamicObject, и Compel преобразовать его в строго типизированный тип. Вышеупомянутый бесшовный код может работать нормально.
c#
c#-3.0
anonymous-types
вспышка
источник
источник
Ответы:
Анонимные типы - это просто неявно объявленные обычные типы. Они не имеют к этому никакого отношения
dynamic
.Теперь, если вы должны использовать ExpandoObject и ссылаться на него через
dynamic
переменную, вы можете добавлять или удалять поля на лету.редактировать
Конечно, можете: просто добавьте его в
IDictionary<string, object>
. Затем вы можете использовать индексатор.Вы используете ту же технику приведения для перебора полей:
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
Приведенный выше код и многое другое можно найти, нажав на эту ссылку.
источник
dynamic o1 = new ExpandObject(); o1."ID" = 1; o1."Name" = "Foo";
((IDictionary<string, object>)o1).Add("Name", "Foo");
. Затем вы можете получить доступ какo1.Name
Вы можете создать ExpandoObject следующим образом:
IDictionary<string,object> expando = new ExpandoObject(); expando["Name"] = value;
И после преобразования его в динамическое значение эти значения будут выглядеть как свойства:
dynamic d = expando; Console.WriteLine(d.Name);
Однако они не являются фактическими свойствами, и к ним нельзя получить доступ с помощью Reflection. Таким образом, следующий оператор вернет null:
d.GetType().GetProperty("Name")
источник
Конечно, можно создавать динамические классы, используя очень крутой класс ExpandoObject. Но недавно я работал над проектом и столкнулся с тем, что Expando Object реализуется в xml не в том же формате, что и простой анонимный класс, было жаль = (, поэтому я решил создать свой собственный класс и поделиться им с вами. Он использует Директива отражения и динамического изменения создает действительно динамическую сборку, класс и экземпляр.Вы можете добавлять, удалять и изменять свойства, которые включены в ваш класс на лету.
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; } } } }
Также очень просто использовать DynamicTypeBuilder, вам просто нужно ввести несколько строк вроде этого:
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; } }
Надеюсь, что этот фрагмент кода кому-нибудь поможет =) Наслаждайтесь!
источник