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
그리고 Scene1 :
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
dynamicObject의 GetType 메소드를 연결할 수 있고 Compel은 강력한 유형의 유형으로 변환합니다. 위의 Seamless 코드는 잘 작동 할 수 있습니다.
답변
익명 형식은 암시 적으로 선언 된 일반 형식입니다. 그들은 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
위의 코드 등은 해당 링크를 클릭하여 찾을 수 있습니다.
답변
다음과 같이 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;
}
}
이 코드 조각이 누군가에게 도움이되기를 바랍니다 =) 즐기십시오!