정확하게 원했던 대답을 찾을 수 없었습니다. 그래서 저는 이것을하기위한 작은 방법을 썼습니다. 같은 시간에 두 개의 객체를 가져 와서 null
값이 할당되지 않은 필드/속성을 나타내는 것으로 가정하면 해당 필드/속성을 병합합니다.
다음은 사용 예입니다. 통신 클래스에 대한 옵션을 보유 할 클래스를 작성하고 통신 클래스에 기본값을 부여한 다음 사용자 설정으로 통신을 초기화하십시오.
예제 설정 클래스입니다.
public class ComSettings
{
public int? Port;
public string? Address;
public bool? KeepAlive;
}
생성자에서 이러한 설정을 사용하는 클래스 예입니다.
public class ComLibrary
{
private static ComSettings _defaults = new ComSettings { Port = 80, Address = "localhost" };
protected ComSettings settings;
public ComLibrary(ComSettings pSettings)
{
this.settings = ObjectMerge<ComSettings>(_defaults, pSettings);
}
}
이렇게하면 다른 클래스가 ComSettings
을 사용하지만 각각 다른 기본값을 가질 수 있습니다. 유일한 제한은 필드/속성이 null
할당을 지원해야한다는 것입니다.
여기 구현은 ObjectMerge
입니다.
/// <summary>
/// Creates a new object that contains the properties of the two objects merged together.
/// </summary>
/// <typeparam name="T">The class type to merge.</typeparam>
/// <param name="pDefaults">Instance of the defaults object.</param>
/// <param name="pSettings">Instance of the settings object.</param>
/// <returns>A new instance of T with the merged results.</returns>
public static T ObjectMerge<T>(T pDefaults, T pSettings, bool pMergeFields = true, bool pMergeProperties = true) where T : class, new()
{
T target = new T();
Type type = typeof(T);
List<MemberInfo> infos = new List<MemberInfo>(type.GetMembers());
foreach (MemberInfo info in infos)
{
// Copy values from either defaults or settings
if (pMergeFields && info.MemberType == MemberTypes.Field)
{
FieldInfo field = (FieldInfo)info;
if (field.IsPublic)
{
object value = field.GetValue(pSettings);
value = (value == null) ? field.GetValue(pDefaults) : value;
field.SetValue(target, value);
}
}
// Copy values from either defaults or settings
if (pMergeProperties && info.MemberType == MemberTypes.Property)
{
PropertyInfo prop = (PropertyInfo)info;
if (prop.CanWrite && prop.CanRead)
{
object value = prop.GetValue(pSettings, null);
value = (value == null) ? prop.GetValue(pDefaults, null) : value;
prop.SetValue(target, value, null);
}
}
}
return target;
}
그리고 여기에 간단한 단위 테스트가 있습니다.
/// <summary>
///This is a test class for CoreUtilsTest and is intended
///to contain all CoreUtilsTest Unit Tests
///</summary>
[TestClass()]
public class CoreUtilsTest
{
/// <summary>
/// A class to perform testing on.
/// </summary>
public class MyClassA
{
public string Param1;
public string Param2;
public string Param3;
}
/// <summary>
/// A class to perform testing on.
/// </summary>
public class MyClassB
{
private string _param1;
public string Param1
{
get { return _param1; }
set { _param1 = value; }
}
private string _param2;
public string Param2
{
get { return _param2; }
set { _param2 = value; }
}
private string _param3;
public string Param3
{
get { return _param3; }
set { _param3 = value; }
}
}
/// <summary>
///A test for SetProperties
///</summary>
[TestMethod()]
public void Merging_Fields()
{
MyClassA defaults = new MyClassA { Param1 = "defaults" };
MyClassA settings = new MyClassA { Param2 = "settings" };
MyClassA results = CoreUtils.ObjectMerge<MyClassA>(defaults, settings);
Assert.AreEqual("defaults", results.Param1);
Assert.AreEqual("settings", results.Param2);
Assert.AreEqual(null, results.Param3);
}
[TestMethod()]
public void Merging_Properties()
{
MyClassB defaults = new MyClassB { Param1 = "defaults" };
MyClassB settings = new MyClassB { Param2 = "settings" };
MyClassB results = CoreUtils.ObjectMerge<MyClassB>(defaults, settings);
Assert.AreEqual("defaults", results.Param1);
Assert.AreEqual("settings", results.Param2);
Assert.AreEqual(null, results.Param3);
}
}
가능한 중복 : http://stackoverflow.com/questions/1358877/what-is-the-best-way-to-merge-two-objects-during-runtime-using-c?rq=1 – cgTag
C#은 정적으로 입력 된 언어이므로 사람들은 C#에서이 작업을 수행하지 않습니다. 문자열은 객체의 속성을 나타내는 데 사용되지 않습니다. 이게 뭘 원해? –
새로운 개체에 대한 속성 그룹을 설정하는 쉬운 방법입니다. – cgTag