2013-10-24 84 views
3

是否有可能有选择地选择(使用装饰器可能?)根据调用的构造函数将对象暴露给哪些方法?有选择地暴露基于构造函数的方法吗?

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

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

    } 

    public MyClass(string filePath) 
    { 
     _filePath = filePath 
    } 

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

是否有可能,当我创建一个新的MyClass的对象,只有当我使用构造函数参数暴露导出方法?

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

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

回答

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 
+0

你仍然有知道哪些键入要使用的问题做。换句话说,这是一个编译时问题。 –

+0

@RobertHarvey在上下文中显示他不需要将变量声明为父类型;它可以是更多的派生类型,所以我没有看到问题。 – Servy

+0

正如我所看到的那样,问题是如果你已经知道对象的类型,那么所有这些都是没有意义的,如果你不知道类型,那么你不能说它是任何特定的派生类型。 –

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; } 
} 

如果你绝对必须有选择性,这在我看来是一个愚蠢的设计决策,那么你会想要去与在运行时使用的代码生成,要么或不执行内置型方法。

0

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

然而,最终,你真正想要的是一个有附加选项的子类。这将是一种更安全的方式来启用这种类型的功能。

1

不是直接。你可以:

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

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

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(); 
    } 
} 
+0

这样做的问题是,您要么必须在两个接口中公开所有MyClass方法,要么将返回对象强制转换回MyClass以访问MyClass方法,这会破坏目的(因为它暴露了这两个接口)。 –