如何将对象创建限制为特定类的方法?

时间:2017-01-03 13:44:44

标签: c#

是否可以将对象创建限制为特定类的方法?

例如:我有一个类Transaction,我想将它的对象创建限制为继承自AbstractService或IService的任何类的方法:

允许的情景:

public class ServiceA : AbstractService (or IService)
{
    public void MethodA() 
    {
        var transaction = new Transaction();
    }

    public void MethodB() 
    {
        var transaction = new Transaction();
    }
}

禁止的情景:

public class ServiceB
{
    public void MethodA() 
    {
        var transaction = new Transaction(); // cannot create
    }

    public void MethodB() 
    {
        var transaction = new Transaction(); // cannot create
    }
}

我可以安装一个访问修饰符或其他东西吗?

3 个答案:

答案 0 :(得分:2)

简短的回答是否定,没有访问修饰符说“此对象只能从实现特定接口的类构造”。

你可以围绕这个限制编写代码,但它远非干净/万无一失。

public class Transaction
{
    private Transaction(){} // private important!

    public static Transaction Create(object creator)
    {
        if(creator is IService)
            return new Transaction();

        throw new InvalidOperationException();
    }
}

public class ServiceA : IService
{
    public void MethodA() 
    {
        var transaction = Transaction.Create(this);  // works
    }
}


public class ServiceB
{
    public void MethodA() 
    {
        var transaction = Transaction.Create(this);  // fails
    }
}

显而易见,以上是多么容易规避。我怀疑你有一个XY Problem并且认为这是解决问题的方法。

答案 1 :(得分:2)

  

我可以安装一个访问修饰符或其他东西吗?

是的其他可以" mount"那种情况,但在我看来,它的工作和抽象很少,很少有奖励。这需要返回Transaction的接口,而不是具体类型。 (我很确定这有效,但我还没有编译它。)

public abstract class AbstractService 
{
}

public interface IService
{
}

public interface ITransaction
{
}


public static class TransactionFactory 
{
    // created them as extensions, but you could remove *this*
    public static ITransaction CreateTransaction(this AbstractService instance)
    {
        return new Transaction ();
    }

    public static ITransaction CreateTransaction(this IService instance)
    {
        return new Transaction ();
    }

    private class Transaction : ITransaction
    {
        public Transaction ()
        {
        }
    }
}

作为旁注,某人在技术上可以传递 null ,因此最好对方法参数进行额外检查(但是,这将是运行时问题而不是编译时问题)。

如果你想编译时检查,我认为你可以做...

public interface ITransactionFactory { }

public abstract class AbstractService : ITransactionFactory { }

public interface IService  : ITransactionFactory { }

public static class TransactionFactory<T>
  where T : ITransactionFactory
{
  public static ITransaction CreateTransaction(this T instance)
    {
        return new Transaction ();
    }
    // ....

不太确定第二个是否正常工作

答案 2 :(得分:2)

也许我误解了你想要做的事情,但看起来这应该可以解决问题:

public abstract class AbstractService : IService
{
    protected class Transaction
    {

    }
}

public class ServiceA : AbstractService
{
    public void MethodA()
    {
        var transaction = new Transaction();
    }

    public void MethodB()
    {
        var transaction = new Transaction();
    }
}

public class ServiceB
{
    public void MethodA()
    {
        var transaction = new Transaction(); // cannot create
    }

    public void MethodB()
    {
        var transaction = new Transaction(); // cannot create
    }
}

internal interface IService
{
}

如果您希望其他任何人能够使用Transaction,您需要让它实现一些公共接口或从其他公共类继承它,但您现在可以确保没有其他人可以创建一个Transaction对象。