如何最好地使用OOP来实现2种不同的数据库系统设计?

时间:2014-04-13 23:57:10

标签: c# oop design-patterns inheritance code-reuse

我需要编写一些中间件代码来在两个第三方学生系统之间移动数据。这些系统都有自己完全不同的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在架构上将这些结合在一起,以便我编写和维护最少量的接线代码? 如果我能减少编码和维护,我想使用继承吗? 有没有更好的方法来解决这个问题?

2 个答案:

答案 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包的核心用例是将数据从一个地方移动到另一个地方。这也称为ETL(提取变换加载)。
  • 视觉显示列及其映射到的内容
  • 可以在SSIS中使用C#
  • 编写自定义模块
  • SSIS包学习曲线真的很低。它们很容易创建。

以下是SSIS的一些缺点: