【问题标题】:C# OOP Cast interface parameter to concrete typeC# OOP 将接口参数转换为具体类型
【发布时间】:2019-01-07 20:55:37
【问题描述】:

我正在尝试为应用程序中的某些基本流程构建一种框架。有一些常见的行为,我必须执行一些操作,但这些操作因某些场景而异。我做了一些我不确定做这样的事情是否被认为是不好的做法:

public interface IMyDto
{
    string makerIdentifier { get; set; }
}

public class DtoOne:IMyDto
{
    public string makerIdentifier { get; set; }
    //Custom properties for ConcreteOne
}

public class DtoTwo:IMyDto
{
    public string makerIdentifier { get; set; }
    //Custom properties for ConcreteTwo
}

public abstract class AbstractMaker
{
    public abstract void DoSomething(IMyDto myInterface);
}

public class ConcreteMakerOne:AbstractMaker
{
    public override void DoSomething(IMyDto myInterface)
    {
        var concrete = myInterface as DtoOne;
        // If concrete is not null..do stuff with DtoOne properties
    }
}

public class ConcreteMakerTwo : AbstractMaker
{
    public override void DoSomething(IMyDto myInterface)
    {
        var concrete = myInterface as DtoTwo;
        // If concrete is not null..do stuff with DtoTwo properties
    }
}

public class Customer
{
    public void MakeSomething(IMyDto myDto)
    {
        var maker = GetMaker();
        maker.DoSomething(myDto);
    }

    private AbstractMaker GetMaker()
    {
        //Stuff to determine if return ConcreteOne or ConcreteTwo
    }
}

我不满意的代码是:

var concrete = myInterface as DtoOne;

如果有人能给我一些关于这种场景的模式或良好 oop 实践的建议或提示,我将不胜感激。

【问题讨论】:

  • 这听起来像是策略模式的一个可能用例
  • "POO" 是什么意思?
  • 什么是创客?看起来您正在使用 Abstract Factory 模式,但您不需要它,因为您没有制作任何东西。就像上面的评论一样,Strategy 模式就足够了。但是,如果您提供一些没有任何模式的代码,然后询问哪种模式最适合这种情况,那就更好了。我认为你过于复杂,过度设计这个。图案是性感的东西,但大多数情况下它只会增加复杂性;尽管有时需要它们。
  • 您的意思是 OOP 而不是 POO?两者有根本不同的含义!
  • 顺便说一句,您不满意的代码是一种令人讨厌的代码气味,我不知道您为什么要强制转换它。只需将其保留为基本接口即可。如果您需要仅存在于具体类中的功能,则该方法应采用具体类。

标签: c# oop design-patterns interface design-principles


【解决方案1】:

尚不清楚您的所有用例是什么,但一种选择可能是泛型:

public abstract class AbstractMaker<T> where T:IMyDto
{
    public abstract void DoSomething(T myInterface);
}

public class ConcreteMakerTwo : AbstractMaker<DtoTwo>
{
    public override void DoSomething(DtoTwo myInterface)
    {
        // now you are certain that myInterface is a DtoTwo
    }
}

【讨论】:

  • 这很有用,但我如何使用泛型实现抽象工厂?
【解决方案2】:

我不确定我是否理解正确你在问什么,但为什么不把方法 DoSomething 放在 IMyDto 中,并在 DtoOne、DtoTwo 等等?只有一个 Maker 并且总是调用相同的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    相关资源
    最近更新 更多