0

コード

public class Test1
{
    [Conversion("UserId")]
    Public int id { get; set; }

    [Conversion("UserValue")]
    public int value { get; set; }

    [Conversion("UserInfo")]
    public List<Test2> info { get; set; }
}
public class User
{
    public int UserId { get; set; }
    public int UserValue { get; set; }      
    public List<UserInformation> UserInfo { get; set; }
}

public class Test2
{
    [Conversion("UserId")]
    public int id { get; set; }

    [Conversion("UserName")]
    public string name { get; set; }

    [Conversion("UserLocation")]
    public string location { get; set; }
}

public class UserInformation
{
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string UserLocation { get; set; }
}

public class ConversionAttribute    
{
    public string Name { get; set; }
    public ConversionAttribute(string name)
    {
        this.Name = name;
    }
}

public dynamic Convert(dynamic source, Type result)
{
    var p = Activator.CreateInstance(result);
    foreach (var item in source.GetType().GetProperties().Where(m => m.GetCustomAttributes(typeof(ConversionAttribute)).Count() > 0))
    {
        p.GetType().GetProperty(item.GetCustomAttributes(typeof(ConversionAttribute)).Cast<ConversionAttribute>().Name).Value = item.GetValue(source,null); // This should work for system types... but not for lists / custom models.          
    }       
}

public void DoShit()
{
    var t1 = new Test1 { id = 1, name = value = "Test", info = new Test2 { id = 1, name = "MyName", location = "UserLocation" } };
    var obj = Convert(t1, typeof(User));
}

状況

私はデータベースモデルをWCFモデルに変換する任務を負っています。これらは、上記のサンプルコードで少し示したいくつかの点で異なります。

を使用してインスタンスを作成するActivator.CreateInstance(result)ことができsource.GetType().GetProperties()、すべてのプロパティをコピーするために使用できますが、モデル(カスタムクラス)またはリストに関しては問題があるようです。

問題

カスタムクラスまたはリスト(システムタイプとカスタムクラスの両方)を処理する方法がわかりません。

以前の方法では、通常の変換とリスト変換の2つの方法を使用していましたが、上司が承認しなかったため、チェックせずに使用ごとに1つの方法を使用できるかどうかを知りたいです。タイプがリスト、カスタムクラス、またはシステムタイプのいずれであるか

これが完全に汎用的であり、属性を使用する必要がある主な理由は、このメソッドを複数のプロジェクトと100を超えるモデルで使用することを計画しているためです。

4

1 に答える 1

0
      Here is something that I tried. It works albeit it's a little slow on lager object graphs. One could use expression trees           which are harder to get but give a really impressive performance.



      'private static IEnumerable<Tuple<PropertyInfo, PropertyInfo>> MapProperties(Type source, Type target)
        {
            var targetProperies = target.GetProperties();

            foreach (var property in source.GetProperties())
            {
                var conversionAttribute =
                    property.GetCustomAttributes(typeof (ConvertAttribute), false).FirstOrDefault() as
                    ConvertAttribute;

                if (conversionAttribute == null)
                    throw new InvalidOperationException(
                        String.Format("Source property {0} doesn't have ConvertAttribute defined", property.Name));

                var targetProperty = targetProperies.FirstOrDefault(p => p.Name == conversionAttribute.Name);


                if (targetProperty == null)
                    throw new InvalidOperationException(String.Format(
                        "Target type doesn't have {0} public property", conversionAttribute.Name));

                yield return Tuple.Create(targetProperty, property);
            }
        }

        public static bool IsIList(Type type)
        {
            return type.GetInterface("System.Collections.Generic.IList`1") != null;
        }


        private static object Convert(object source, Type resaultType)
        {
            var resault = Activator.CreateInstance(resaultType);

            var sourceType = source.GetType();


            if (IsIList(resaultType) && IsIList(sourceType))
            {
                var sourceCollection = source as IList;

                var targetCollection = resault as IList;

                var argument = resaultType.GetGenericArguments()[0];

                if (argument.IsAssignableFrom(sourceType.GetGenericArguments()[0]))
                {
                    foreach (var item in sourceCollection)
                    {
                        targetCollection.Add(item);
                    }
                }
                else
                {
                    foreach (var item in sourceCollection)
                    {
                        targetCollection.Add(Convert(item, argument));
                    }
                }
            }
            else
            {
                foreach (var map in MapProperties(sourceType, resaultType))
                {
                    if (map.Item1.PropertyType.IsAssignableFrom(map.Item2.PropertyType))
                    {
                        map.Item1.SetValue(resault, map.Item2.GetValue(source, null), null);
                    }
                    else
                    {
                        map.Item1.SetValue(resault,
                                           Convert(map.Item2.GetValue(source, null), map.Item1.PropertyType), null);
                    }
                }
            }
            return resault;
        }'
于 2013-02-22T11:09:50.617 に答える