Jon Skeets 속성 복사를 사용하여 복사기를 만들려고합니다. 그것은 모든 속성,하지만 enums 잘 작동합니다. 열거 형을 거의 성공하지 못하게하려면 메서드를 변경하는 시도를 여러 번 시도했습니다. 다른 사람이이 작업을 수행하는 방법에 대한 아이디어가 있는지 궁금합니다.엔티티 int가 POCO의 Entum 인 Entity 객체를 POCO에 복사합니다.
존 Skeets 원래 내 변경이에 BUILDCOPIER 방법에 의견
호출을 구분 함께있는
var result = Common.PropertyCopy<POCO>.CopyFrom(Entity);
원래 존 소총 코드
/// <summary>
/// Generic class which copies to its target type from a source
/// type specified in the Copy method. The types are specified
/// separately to take advantage of type inference on generic
/// method arguments.
/// http://www.yoda.arachsys.com/csharp/miscutil/
/// </summary>
public static class PropertyCopy<TTarget> where TTarget : class, new()
{
/// <summary>
/// Copies all readable properties from the source to a new instance
/// of TTarget.
/// </summary>
public static TTarget CopyFrom<TSource>(TSource source) where TSource : class
{
return PropertyCopier<TSource>.Copy(source);
}
/// <summary>
/// Static class to efficiently store the compiled delegate which can
/// do the copying. We need a bit of work to ensure that exceptions are
/// appropriately propagated, as the exception is generated at type initialization
/// time, but we wish it to be thrown as an ArgumentException.
/// </summary>
private static class PropertyCopier<TSource> where TSource : class
{
private static readonly Func<TSource, TTarget> copier;
private static readonly Exception initializationException;
internal static TTarget Copy(TSource source)
{
if (initializationException != null)
{
throw initializationException;
}
if (source == null)
{
throw new ArgumentNullException("source");
}
return copier(source);
}
static PropertyCopier()
{
try
{
copier = BuildCopier();
initializationException = null;
}
catch (Exception e)
{
copier = null;
initializationException = e;
}
}
private static Func<TSource, TTarget> BuildCopier()
{
ParameterExpression sourceParameter = Expression.Parameter(typeof(TSource), "source");
var bindings = new List<MemberBinding>();
foreach (PropertyInfo sourceProperty in typeof(TSource).GetProperties())
{
if (!sourceProperty.CanRead)
{
continue;
}
PropertyInfo targetProperty = typeof(TTarget).GetProperty(sourceProperty.Name);
if (targetProperty == null)
{
throw new ArgumentException("Property " + sourceProperty.Name + " is not present and accessible in " + typeof(TTarget).FullName);
}
if (!targetProperty.CanWrite)
{
throw new ArgumentException("Property " + sourceProperty.Name + " is not writable in " + typeof(TTarget).FullName);
}
// THIS IS FALSE FOR SOURCE(INT) TARGET ENUMS
if (!targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
{
//ADDED FOLLOWING TO HANDLE COPY FROM INT TO ENUM
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Special Case because Entities are created with property as ints, not enum types
if (targetProperty.PropertyType.IsEnum && (sourceProperty.PropertyType == typeof(int)))
{
var expressionparam = Expression.Parameter(sourceProperty.PropertyType);
// cast the entity source as the enum target
var cast = Expression.Convert(expressionparam, targetProperty.PropertyType);
// add to the binding tree
bindings.Add(Expression.Bind(targetProperty, Expression.Property(cast, sourceProperty)));
continue;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
throw new ArgumentException("Property " + sourceProperty.Name + " has an incompatible type in " + typeof(TTarget).FullName);
}
Expression initializer = Expression.MemberInit(Expression.New(typeof(TTarget)), bindings);
return Expression.Lambda<Func<TSource, TTarget>>(initializer, sourceParameter).Compile();
}
}
}
열거
public enum NotificationType
{
InAppNotificiation = 0,
EmailNotification,
SMS
}
유형 'Models.Enums에 대해 정의되지 않은3210
엔티티 클래스 EF하여 라인
bindings.Add(Expression.Bind(targetProperty, Expression.Property(cast, sourceProperty)));
재산권'INT32 NotificationType '던져
public class Entity
{
public int ProcessedStatus { get; set; }
public int Priority { get; set; }
public System.Guid NotifyToUserId { get; set; }
public string NotifyFrom { get; set; }
public string NotifySubject { get; set; }
public string NotifyMessageBody { get; set; }
public int NotificationType { get; set; } <-- Stored as int in DB
public virtual MercuryUser MercuryUser { get; set; } <--complex type
}
POCO 클래스
public class POCO
{
public int ProcessedStatus { get; set; }
public int Priority { get; set; }
public System.Guid NotifyToUserId { get; set; }
public string NotifyFrom { get; set; }
public string NotifySubject { get; set; }
public string NotifyMessageBody { get; set; }
public NotificationType NotificationType { get; set; } <-- ENUM TYPE
public MyUser MyUser { get; set; } <-- complex type
}
예외를 생성합니다. 알림 유형
EF는 코드 우선 POCO와 enum (버전 5 이후)을 지원하므로 더 이상 하나의 객체를 다른 객체로 복사 할 필요가 없습니다. –
프로젝트 결정에 앞서 디자인 결정이 내려졌고 코드가 처음 사용되지 않았습니다. – DRobertE
대상 클래스를 작성할 때 코드를 효과적으로 복제하지 않습니까? 어쨌든 AutoMapper와 같은 매핑 라이브러리를 사용하여 리플렉션 코드를 직접 작성하지 않고 하나의 DTO를 다른 맵핑에 매핑 할 수 있습니다. 매핑 라이브러리는 또한 캐싱 매핑을 처리하므로 새 객체를 매핑 할 때마다 속성 검색을 반복하지 않아도됩니다. –