【问题标题】:How to avoid casting between the DL - BL - UI layers ? (C#)如何避免在 DL-BL-UI 层之间进行转换? (C#)
【发布时间】:2011-06-19 07:25:34
【问题描述】:

我设计的应用程序基本上有 3 个不同的逻辑层:

  1. DB 连接器(由 ADO.NET 实现)。
  2. BL 业务逻辑(UI 唯一知道的)。
  3. 数据库存储库(连接前两个存储库)。

数据库存储库被分成依赖的部分,每个最终实体都多态到一个接口。在某些情况下,相同依赖部分内的对象之间存在依赖关系 - ISectionFactory(因此依赖)。 在实践中,BL 会从 MainFactory 请求一个特定类型的对象(例如我的示例中的 IngrediantType)(这是所有 DB 的一个因素) 由于这种设计,我不得不在 UI 上强制转换类型——这显然是一种拖累。 我怎样才能改变设计? 以下是设计的简要介绍:

public class MainFactory
{
    private Dictionary<Type, ISectionFactory> m_SectionsFactories;
    private ISectionFactory treatmentsSectionFactory = 
            new TreatmentsSectionFactory();

    public MainFactory()
    {
        m_SectionsFactories = new Dictionary<Type, ISectionFactory>
            {
                {typeof(IngrediantType),treatmentsSectionFactory}
            };
    }

    public IConcreteDataCollection GetConcreteData(Type i_EntitiesName)
    {
        return m_SectionsFactories[i_EntitiesName]
            .GetConcreteData(i_EntitiesName);
    }
}

internal interface ISectionFactory
{
    IConcreteDataCollection GetConcreteData(Type i_EntitiesName);
}

public class TreatmentsSectionFactory : ISectionFactory
{
    private Dictionary<Type, IConcreteDataCollection> 
            m_ConcreteDataCollections;

    private IngrediantTypes m_IngrediantTypes = new IngrediantTypes();
    private Ingrediants m_Ingrediants = new Ingrediants();

    public TreatmentsSectionFactory()
    {
        m_ConcreteDataCollections = 
            new Dictionary<Type, IConcreteDataCollection>();
        m_ConcreteDataCollections
            .Add(typeof(IngrediantType), m_IngrediantTypes);
        m_ConcreteDataCollections
            .Add(typeof(Ingrediants), m_Ingrediants);
    }

    public IConcreteDataCollection GetConcreteData(Type i_EntitiesName)
    {
        return m_ConcreteDataCollections[i_EntitiesName];
    }
}

public interface IConcreteDataCollection : IEnumerable
{
    // Iteratable.
    IConcreteData GetById(int i_Id);
    void AddNewConcreteData(IConcreteData i_ConcreteData);
    void UppdateConcreteData(IConcreteData i_ConcreteData);
    void DeleteConcreteData(IConcreteData i_ConcreteToDelete);
}

public class IngrediantTypes : IConcreteDataCollection
{
    public string TestType { get; set; }
    public IConcreteData GetById(int i_Id){}
    public void AddNewConcreteData(IConcreteData i_ConcreteData){}
    public void UppdateConcreteData(IConcreteData i_ConcreteData){}
    public void DeleteConcreteData(IConcreteData i_ConcreteToDelete){}        
    public IEnumerator GetEnumerator(){}
}

// also implements IConcreteDataCollection
public class Ingrediants : IConcreteDataCollection 
{
}

public interface IConcreteData
{
    public int Index { set; get; }        
} // the final (highest) entity of all DB entities

public class IngrediantType : IConcreteData
{
    public int Index { set; get; }
    // other set of properties
}

public class Ingrediant : IConcreteData
{
    public int Index { set; get; }
    public IngrediantType RelatedIngrediantType { set; get; }
    // other set of properties
}

public class mainClass
{
    public static void main()
    {
        MainFactory factory = new MainFactory();

        var type = typeof(IngrediantType);

        // returns a IngrdiantTypes of type (IConcreteDataCollection)
        var t = factory.GetConcreteData(typeof(IngrediantType)); 

        // I want to use the IngrediantType without casting !!!
        var s = t.GetById(2); 
    }
}

【问题讨论】:

    标签: casting business-logic facade


    【解决方案1】:

    很难说出这里发生了什么,但我认为关键是要像这样利用泛型:

    public IConcreteDataCollection<T> GetConcreteData<T>()
    {
        return ...;
    }
    

    如果我正确理解你的问题,这将允许你说:

    var t = factory.GetConcreteData<IngrediantType>(); 
    

    您几乎需要更改代码中的每个类以使用泛型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-26
      • 2015-04-01
      • 1970-01-01
      • 2017-09-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多