我需要编写一些中间件代码来在两个第三方学生系统之间移动数据。这些系统都有自己完全不同的Web Service API。 我的计划是在每个Web Service API的顶部构建自定义包装器,然后在两个Wrappers的顶部构建一个Common程序集,以在系统之间移动数据,并允许在公共代码库上进一步开发。大约有12个其他应用程序直接使用这些系统,维护变得难以管理。我想构建一些可以迁移到的东西。
在伪代码中
//System one out puts
Class Student_SytemA {
Public StudentID {get;set;} //PKID System A
Public FName {get;set;}
Public LName {get;set;}
Public DOB {get;set;}
}
//System two out puts
Class Student_SystemB{
Public ContactID {get;set;} //PK SystemB
Public FirstName {get;set;}
Public LastName {get;set;}
Public DateOfBirth {get;set;}
Public StudentID_REF {get;set;} //Reference to System A
}
这种事情在两个系统中都是流行的,它们在不同的字段名称或数据结构下保存完全相同的信息。
我的想法是有这样的东西
Class Student_Comman{
Public ContactID {get;set;}
Public FirstName {get;set;}
Public LastName {get;set;}
Public DateOfBirth {get;set;}
Public StudentID_REF {get;set;}
Public WireUpSystemA(Student_SystemA student){
StudentID_REF = student .StudentID;
FirstName = student .FName ;
LastName = student .LName ;
DateOfBirth = student .DOB ;
}
Public WireUpSystemB(Student_SystemB student){
StudentID_REF = student . StudentID_REF ;
FirstName = student . FirstName ;
LastName = student . LastName;
DateOfBirth = student . DateOfBirth;
}
}
我如何使用OOP在架构上将这些结合在一起,以便我编写和维护最少量的接线代码? 如果我能减少编码和维护,我想使用继承吗? 有没有更好的方法来解决这个问题?
答案 0 :(得分:0)
对于像你这样的案例,我更喜欢反思/通用方法。
使用一个属性标记A和B的属性,该属性告知必须在目标类型中映射哪个属性并创建一个通用转换器:
//Custom attribute class
sealed class RedirectedPropertyAttribute : Attribute
{
readonly string targetProperty;
public RedirectedPropertyAttribute(string TargetProperty)
{
this.targetProperty = TargetProperty;
}
public string TargetProperty
{
get { return targetProperty; }
}
}
//Type converter
public class TypeConverter
{
public static T Convert<T, S>(S Source) where T : class, new() where S : class, new()
{
//If no instance is passed just return null
if (Source == null)
return null;
//Get types of items
Type typeOfTarget = typeof(T);
Type typeOfSource = typeof(S);
//Get properties of items
var sourceProperties = typeOfSource.GetProperties();
var targetProperties = typeOfTarget.GetProperties();
//Create a new instance of T
var instance = Activator.CreateInstance<T>();
foreach (var prop in sourceProperties)
{
//Get or attributes
var attribs = prop.GetCustomAttributes(typeof(RedirectedPropertyAttribute), false); //If you want to inherit the attributes change to yes
//If it's not marked or marked more than once, continue (really a bad error ;))
if (attribs == null || attribs.Length != 1)
continue;
//Cast the attribute
RedirectedPropertyAttribute attrib = attribs[0] as RedirectedPropertyAttribute;
//No property set? ignore this property
if (string.IsNullOrWhiteSpace(attrib.TargetProperty))
continue;
//Find the target property in target type
var tProp = targetProperties.Where(t => t.Name == attrib.TargetProperty).FirstOrDefault();
//Not found? ignore this property
if (tProp == null)
continue;
try
{
//Why this try-catch?
//Because if types don't match an exception can be thrown
//but it's easier than comparing types (because if an int is mapped to a long we want it to be set)
//WARNING!!, assuming non-indexed properties!
tProp.SetValue(instance, prop.GetValue(Source, null), null);
}
catch { }
}
//Return new class
return instance;
}
}
//Class from source A
public class A
{
[RedirectedProperty("Id")]
public int IdOfA { get; set; }
[RedirectedProperty("Name")]
public string StringOfA { get; set; }
}
//Class from source B
public class B
{
[RedirectedProperty("Id")]
public int IdOfB { get; set; }
[RedirectedProperty("Name")]
public string StringOfB { get; set; }
}
//Hub class for A or B
public class ABHub
{
public int Id { get; set; }
public string Name { get; set; }
}
//And to use:
ABHub ACasted = TypeConverter.Convert<ABHub, A>(new A{ IdOfA = 33, StringOfA = "MyNameIsA" });
ABHub BCasted = TypeConverter.Convert<ABHub, B>(new B{ IdOfB = 33, StringOfB = "MyNameIsB" });
答案 1 :(得分:0)
在两个第三方系统之间移动数据可能会非常棘手,尤其是如果它们可能会改变它们所暴露的属性/方法。
项目的范围是否只是在两个系统之间来回移动数据?如果是这样,请查看SSIS包。
以下是SSIS的一些好处:
以下是SSIS的一些缺点: