有选择地暴露基于构造函数的方法?

时间:2013-10-24 19:18:07

标签: c# constructor decorator

是否有可能选择性地选择(使用装饰器?)基于被调用的构造函数向对象公开的方法是什么?

例如,我的类有2个构造函数,一个空构造函数和一个传入文件路径字符串的构造函数。

public class MyClass
{
    private readonly string _filePath;
    public MyClass()
    {

    }

    public MyClass(string filePath)
    {
         _filePath = filePath
    }

    public Export()
    {
        var fi = new FileInfo(_filePath);
    }
}

当我创建一个新的MyClass对象时,是否有可能只使用带有参数的构造函数来公开Export方法?

var myClass = new MyClass();
//myClass.Export() not available

var myClass = new MyClass(@"C:\");
//myClass.Export() is available

5 个答案:

答案 0 :(得分:1)

这表明您应该有两种不同的类型。也许它们都应该是父类型的子类型(可能是抽象的),或者也许应该只是扩展另一类。

然后,您可以根据是否有字符串构造适当类型的实例。带字符串的类型可以有一个额外的方法。

public class MyClass
{
    public MyClass()
    {

    }

    public void Foo()
    {
        //todo do stuff
    }
}

public class BetterMyClass : MyClass
{
    private readonly string _filePath;

    public BetterMyClass(string filePath)
    {
        _filePath = filePath;
    }

    public void Export()
    {
        var fi = new FileInfo(_filePath);
    }
}

然后你的用法就可以了:

var myClass = new MyClass();
//myClass.Export(); //syntax error

var myClass2 = new BetterMyClass(@"C:\");
myClass.Export(); //works

答案 1 :(得分:1)

不直接。你可以:

  1. 创建一个返回类型为IMyInterface的对象的工厂方法,然后尝试强制转换为包含要公开的方法的类型。如果对象不是暴露方法的类型,则强制转换将失败。或..

  2. 使用dynamic个对象。如果方法不存在,方法调用将在运行时失败。

答案 2 :(得分:0)

这是可能的,只是不是你在这里展示的方式。您可能希望创建一个只有默认构造函数且没有Export方法的新类。然后创建一个继承自第一个类的第二个类,并使用一个需要string的构造函数,并公开Export方法。

public class MyClass
{
    public MyClass()
    { }
}

public class MyOtherClass : MyClass
{
    private readonly string value;

    public MyOtherClass(string value)
    {
        this.value = value;
    }

    public string Export() { return this.value; }
}

如果你绝对必须具有选择性,这在我看来是一个愚蠢的设计决定,那么你会想要使用在运行时使用代码生成构建的类型,该代码生成或不实现该方法。

答案 3 :(得分:0)

据我所知,不,这不可能以你的意思完成。如果可以的话,编译器通常无法知道相关方法是否对相关对象有效。然后它必须在运行时检查。如果在不可用时调用该方法,则会收到运行时异常。您可以根据构造函数中设置的标志自行抛出异常。

但是,最终,您真正想要的是一个具有其他选项的子类。这将是一种更安全的方式来启用此类功能。

答案 4 :(得分:0)

您可以使用工厂模式执行此操作并返回不同的界面

public interface IExportInterface
{
    void Export();
}

public interface INoExportInterface
{
    //Other methods
}

internal class MyClass : IExportInterface, INoExportInterface
{
    private readonly string _filePath;

    public MyClass()
    {
    }

    public MyClass(string filePath)
    {
        _filePath = filePath;
    }

    public void Export()
    {
        var fi = new FileInfo(_filePath);
    }
}

public class MyClassFactory
{
    public static IExportInterface GetMyClass(string filePath)
    {
        return new MyClass(filePath);
    }

    public static INoExportInterface GetMyClass()
    {
        return new MyClass();
    }
}