0

重複の可能性:
C#でオブジェクトを複製する

私がやりたいのは、クラス内の値をあるオブジェクトから別のオブジェクトにコピーすることです。浅いコピーで十分です。ただし、オブジェクトがリスト/ array/ienumerableに対して持っている参照を失いたくありません。また、私もこれをやりたくありません:

public static void EditEvent(EventModel editEvent)
{
    EventModel changingEvent = EventRepository.getEvent(editEvent.EventID);
    changingEvent.Subject = editEvent.Subject;
    changingEvent.EventDate = editEvent.EventDate;
    changingEvent.EventDesc = editEvent.EventDesc;
    changingEvent.DayCode = editEvent.DayCode;
}

むしろ:

public static void EditEvent(EventModel editEvent)
{
    EventModel changingEvent = EventRepository.getEvent(editEvent.EventID);
    changingEvent.CopyFrom(editEvent);
    //or
    editEvent.CopyTo(changingEvent);
}
4

3 に答える 3

1

これは私が今日書いたコードです。簡単なテストに合格します。私はあなたがそれを使って始めることができると思っています。

テストは次のとおりです。

    /// <summary>
    ///A test for MapProperties
    ///</summary>
    public void MapPropertiesTestHelper<S, T>(S source, T target1, bool failIfNotMatched)
    {
        Cake.Common.Mapper<S, T> target = new Cake.Common.Mapper<S, T>();
        target.MapProperties(source, target1, failIfNotMatched);
    }

    [TestMethod()]
    public void MapPropertiesTest()
    {
        var source = new Source {
            OneTwo = 10,
            ThreeFour = "foo"
        };

        var target = new Target {
            OneTwo = 10,
            ThreeFour = "bar"
        };

        MapPropertiesTestHelper<Source, Target>(source, target, true);

        Assert.AreEqual(source.OneTwo, target.OneTwo);
        Assert.AreEqual(source.ThreeFour, target.ThreeFour);
        Assert.AreEqual(source.five_six, target.FiveSix);
    }

    public class Source
    {
        public int OneTwo { get; set; }
        public string ThreeFour { get; set; }
        public bool five_six { get; set; }
    }

    public class Target
    {
        public int OneTwo { get; set; }
        public string ThreeFour { get; set; }
        public bool FiveSix { get; set; }
    }

そしてここにコードがあります:

public class MapperItem
{
    public MapperItem(MemberInfo member, object o)
    {
        this.Member = member;
        this.Object = o;
    }

    public MemberInfo Member 
    { 
        get; 
        set; 
    }

    public object Object
    {
        get;
        set;
    }

    public Type Type
    {
        get
        {
            return this.Member.UnderlyingType();
        }
    }

    public object Value
    {
        get
        {
            if (this.Member is PropertyInfo)
            {
                return (this.Member as PropertyInfo).GetValue(this.Object, null);
            }
            else if (this.Member is FieldInfo)
            {
                return (this.Member as FieldInfo).GetValue(this.Object);
            }
            else
            {
                throw new Exception("sourceMember must be either PropertyInfo or FieldInfo");
            }
        }
    }

    public object Convert(Type targetType)
    {
        object converted = null;

        if (this.Value == null)
        {
            return converted;
        }
        else if (targetType.IsAssignableFrom(this.Type))
        {
            converted = this.Value;
        }
        else
        {
            var conversionKey = Tuple.Create(this.Type, targetType);
            if (Conversions.ContainsKey(conversionKey))
            {
                converted = Conversions[conversionKey](this.Value);
            }
            else
            {
                throw new Exception(targetType.Name + " is not assignable from " + this.Type.Name);
            }
        }

        return converted;
    }

    public void Assign(object value)
    {
        if (this.Member is PropertyInfo)
        {
            (this.Member as PropertyInfo).SetValue(this.Object, value, null);
        }
        else if (this.Member is FieldInfo)
        {
            (this.Member as FieldInfo).SetValue(this.Object, value);
        }
        else
        {
            throw new Exception("destinationMember must be either PropertyInfo or FieldInfo");
        }
    }

    public static Dictionary<Tuple<Type, Type>, Func<object, object>> Conversions = new Dictionary<Tuple<Type, Type>, Func<object, object>>();
}

public class Mapper<S, T>
{
    private List<string> ignoreList = new List<string>();
    public List<string> IgnoreList
    {
        get { return ignoreList; }
        set { ignoreList = value; }
    }

    public void MapProperties(S source, T target, bool failIfNotMatched = true)
    {
        foreach (PropertyInfo property in source.GetType()
                                                      .GetProperties()
                                                      .Where(c => !IgnoreList.Contains(c.Name)))
        {
            try
            {
                var sourceField = new MapperItem(property, source);
                var targetField = new MapperItem(MatchToTarget(property), target);
                targetField.Assign(sourceField.Convert(targetField.Type));
            }
            catch (TargetNotMatchedException noMatch)
            {
                if (failIfNotMatched)
                {
                    throw noMatch;
                }
            }
        }
    }

    private MemberInfo MatchToTarget(MemberInfo member)
    {
        List<MemberInfo> members = new List<MemberInfo>();
        members.AddRange(typeof(T).GetProperties());
        members.AddRange(typeof(T).GetFields());

        var exactMatch = from c in members where c.Name == member.Name select c;

        if (exactMatch.FirstOrDefault() != null)
        {
            return exactMatch.First();
        }

        var sameAlphaChars = from c in members
                             where NormalizeName(c.Name) == NormalizeName(member.Name)
                             select c;

        if (sameAlphaChars.FirstOrDefault() != null)
        {
            return sameAlphaChars.First();
        }

        throw new TargetNotMatchedException(member, typeof(T));
    }

    private static string NormalizeName(string input)
    {
        string normalized = input.Replace("_", "").ToUpper();
        return normalized;
    }
}

public class TargetNotMatchedException : Exception
{
    public TargetNotMatchedException(MemberInfo member, Type type)
        : base("no match for member named " + member.Name + " with type named " + type.Name)
    {
        this.Member = member;
        this.Type = type;
    }
    public MemberInfo Member { get; set; }
    public Type Type { get; set; }
}

public static class ReflectionExtensions
{
    public static Type UnderlyingType(this MemberInfo member)
    {
        Type type;
        switch (member.MemberType)
        {
            case MemberTypes.Field:
                type = ((FieldInfo)member).FieldType;
                break;
            case MemberTypes.Property:
                type = ((PropertyInfo)member).PropertyType;
                break;
            case MemberTypes.Event:
                type = ((EventInfo)member).EventHandlerType;
                break;
            default:
                throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", "member");
        }
        return Nullable.GetUnderlyingType(type) ?? type;
    }
}
于 2012-04-20T21:32:32.823 に答える
1

あなたはこのようにすることができます

public class MyClonableClass : ICloneable
{
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

厳密に型指定されたメソッドを使用したい場合は、インターフェースを忘れてください

public class MyClonableClass
{
    public MyClonableClass Clone()
    {
        return (MyClonableClass)this.MemberwiseClone();
    }
}

これは、あるオブジェクトのフィールドを別のオブジェクトにコピーするのではなく、元のオブジェクトの正確な複製である新しいオブジェクトを作成します。浅いコピーを作成します。

于 2012-04-20T20:29:48.593 に答える
0

Object.MemberwiseClone メソッドが必要です

于 2012-04-20T20:28:51.480 に答える