根据使用的构造函数有选择地公开方法

本文关键字:选择地 方法 构造函数 | 更新日期: 2023-09-27 18:36:56

是否可以

有选择地选择(也许使用装饰器?)基于调用的构造函数向对象公开哪些方法?

例如,我的类有 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

根据使用的构造函数有选择地公开方法

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

然后,可以根据是否具有字符串来构造适当类型的实例。 带有字符串的类型可以具有其他方法。

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. 创建一个返回类型 IMyInterface 对象的工厂方法,然后尝试强制转换为包含要公开的方法的类型。 如果对象不是公开方法的类型,则强制转换将失败。 或。。

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

这是可能的,只是不是你在这里显示的方式。您可能希望创建一个只有默认构造函数而没有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; }
}

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

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

然而,最终,你真正想要的很可能是一个具有其他选项的子类。 这将是启用此类功能的更安全方法。

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

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