1

可以使用什么实用程序或模式来解决此问题?我不知道有什么可以帮助解决这个问题。我们可以使用某种类型的模式吗?

如果您有以下抽象类:

abstract class Foo
{
    function void Something()
    {
    // Get the media type
    }
}

以及从该类派生的以下类:

class Foo1 : Foo
{
    public string MyId {get;set}
    public string MyFile {get;set}
    public TxtFile MyTextFile {get;set}

    function void myFooFunction()
    {
    // Save File to Txt
    }
}

class Foo2 : Foo
{
    public string MyId {get;set}
    public string MyFile {get;set}
    public XMLFile MyXMLFile {get;set}

    function MyOtherFunction()
    {
    // Save to XML
    }
}

然后在存储库中的 Linq(或类似)中,您执行以下操作:

var a = (from e in db.myTable
        where e.myFileType == "XML"
        Select e);

然后我们必须将它映射到正确的对象。像这样:

Foo newFoo = FooFactory.CreateFooFor(a.myFileType.ToString())
newFoo.MyId = a.id;
newFoo.MyFile = a.myfile;
newFoo.MyXMLFile = a.xml;

工厂当然有帮助,但是您如何为多个“文件类型”(例如 txt)执行此操作?字段不匹配!

我是否必须编写更多执行相同操作的代码?我觉得必须有一些东西可以做到这一点。

4

3 回答 3

1

首先,如果myFooFunctionMyOtherFunction都用于保存,则可以使用策略模式,只需定义和抽象Save()方法在派生类中实现。您还可以查看模板方法模式。

虽然这不完全是一种模式,但您可能还想在此处应用“上拉字段”重构并将MyIdandMyFile属性放在父类中。

对于创作...

Builder 模式类似于工厂,但允许创建更复杂的对象。我不知道它是否适合这个简化的示例,但它可能适合您在真实代码中实际尝试做的事情。可能不是。我只是先提一下,因为它是我心目中最接近工厂的地方。

还有映射器模式和数据映射器模式。您可以将映射封装在一个对象中并让工厂返回一个映射器:

    FooMapper mapper = FooMapperFactory.CreateFooMapperFor(a.myFileType);
    Foo newFoo = mapper.CreateFoo(a);
于 2013-09-20T20:31:39.093 回答
0

如果您考虑对从数据库返回的数据使用反射,或者可能是适配器模式,您可以设置一种动态方式将字段相互映射。使用反射(以下是伪逻辑,因为反射是一种混乱的代码):

  • 从目标类型获取所有公共属性的 PropertyInfo 对象列表
  • 从数据库类型中获取所有公共属性的 PropertyInfo 对象列表
  • 比较它们的名称/类型以创建映射
  • 使用反射将数据库类型中的值分配给目标类型

像这样的东西可以解决问题:

public void AssignAndMapTypes<DatabaseType, TargetType>(DatabaseType db, ref TargetType target)
    {
        var dbType = db.GetType();
        var dbTypeProperties = dbType.GetProperties(System.Reflection.BindingFlags.Public);

        var targetType = target.GetType();
        var targetTypeProperties = targetType.GetProperties(System.Reflection.BindingFlags.Public);

        foreach (var prop in targetTypeProperties)
        {
            var matchingProp = dbTypeProperties.Where(e => { return (string.Compare(e.Name, prop.Name, true) == 0) && (e.PropertyType == prop.PropertyType) }).FirstOrDefault();

            if(matchingProp != null)
            {
                prop.SetValue(target, matchingProp.GetValue(db, null), null);
            }
        }
    }
于 2013-09-20T20:10:24.300 回答
0

我相信您可以使用泛型解决您的问题。我冒昧地更改了一些代码。这行得通吗?

public abstract class Foo
{
    public abstract void Save();
    public void Something()
    {
        // Get the media type
    }
}

public class FooText : Foo
{
    public string MyId { get; set; }
    public string MyFile { get; set; }
    public string MyTextFile { get; set; }

    public override void Save()
    {
        // Save File to Txt
    }
}

public class FooXml : Foo
{
    public string MyId { get; set; }
    public string MyFile { get; set; }
    public string MyXMLFile { get; set; }

    public override void Save()
    {
        // Save to XML
    }
}

public class FooFactory<T> where T : Foo, new()
{
    public static T CreateFoo()
    {
        return new T();
    }
}
于 2013-09-20T20:16:16.523 回答