创建一个接口实例

26

我定义了以下接口:

public interface IAudit {
    DateTime DateCreated { get; set; }
}

public interface IAuditable {
    IAudit Audit { get; set; }
}

IAuditable接口定义了哪些类我将具有AuditIAudit接口是该类的实际Audit。例如,假设我有以下实现:

public class User : IAuditable {
    public string UserName { get; set; }
    public UserAudit Audit { get; set; }
}

public class UserAudit : IAudit {
    public string UserName { get; set; }
    public DateTime DateCreated { get; set; }

    public UserAdit(User user) {
        UserName = user.UserName;
    }
}

现在有一个对象是IAuditable(来自上面的User),我想通过将IAuditable对象传递给构造函数来创建IAudit实例(来自上面的UserAdit)。理想情况下,我希望有这样的代码:

if (myObject is IAuditable) {
    var audit = new IAudit(myObject) { DateCreated = DateTime.UtcNow }; // This would create a UserAudit using the above example
}

然而我有一堆问题:

  • 你无法创建接口的实例
  • 代码中没有明确定义哪个 IAudit 适用于哪个 IAuditable
  • 我无法指定 IAudit 接口必须具有以 IAuditable 为参数的构造函数

我确定这是许多人曾经遇到的设计模式,但我无法理解它。如果有人能向我展示如何实现这一点,我会非常感激。

6个回答

19

你不能创建接口的实例。

正确。你需要创建一个实现该接口的对象的实例:

IAuditable myUser = new User();

代码中没有定义哪个IAudit适用于哪个IAuditable

你无法直接使用一个接口来完成此操作,需要重新考虑你的设计。

你可以在接口中使用开放式泛型类型,并使用封闭类型实现它:

public interface IAudit<T> {
    DateTime DateCreated { get; set; }
}

public class UserAudit : IAudit<User> {
    public string UserName { get; set; }
    public DateTime DateCreated { get; set; }

    public UserAdit(User user) {
        UserName = user.UserName;
    }
}

我无法指定IAudit接口必须有一个接受IAuditable的构造函数。

是的,你确实不能。请参见这里。您需要在实现者中创建这样的构造函数。


对于提问者来说,这是一个有用的答案和有用的信息,但仍然过于注重C#/.NET的细节,以至于我暂时不会给它点赞。Tridus则从我的角度解决了真正的问题。尽管如此,这些信息对于提问者仍然很有用。 - Marijn
嗨,谢谢,我已经接受了@Tridus的答案,但我使用了你的建议来帮助。 - nfplee
为什么我们要这样做,而不是像User user = new User()一样创建它?声明为IAuditable myUser = new User()有什么好处? - Berke Kaan Cetinkaya

18

在代码中没有定义哪个IAudit适用于哪个IAuditable,我无法指定IAudit接口必须有一个接受IAuditable的构造函数。

你可以通过在IAuditable中添加CreateAudit()函数来解决这两个问题。然后你将从IAuditable创建一个IAudit。如果你想要在IAuditable(或反之)中存储对IAudit的引用,以便让它们相互关联,那么实现类很容易做到这一点。例如,你还可以在IAudit中添加GetAuditable()函数,以获取其创建自哪个IAuditable

简单实现可能如下所示(在实现IAuditable的类上):

public IAudit CreateAudit()
{
    UserAudit u = new UserAudit(UserName);
    return u;
}

2
+1 正是我即将发布的答案,但你似乎更早地真正理解了问题。 - Marijn
@nfplee:你实际上在问一个设计问题,而你想要的答案并不在于C#/.NET的具体细节。这就是你的答案,或者至少让你朝着正确的方向前进了一步。 - Marijn
@Tridus:感谢你的回答,但现在已经是周五下午了,我显然已经傻掉了哈哈。如果我尝试说 ((IAuditable)myObject).CreateAudit(),它会找不到 CreateAudit 方法。我相信我已经按照你说的做了一切。 - nfplee
@Tridus:请不要理我,我真的应该学会更多地构建代码,而不是过度依赖智能感知。再次感谢您的帮助。 - nfplee

7

显然你不能创建一个接口的实例,但如果你真的想创建传入类的实例,你可以这样做:

IAuditable j = ((IAuditable)Activator.CreateInstance(myObject.GetType()));

你需要知道要构造哪个具体类,在你的例子中,唯一的选择是myObject。
另外,你可以研究一些叫做“依赖注入”的东西,它允许你指定将哪种类型的具体类“注入”到调用构造函数中接口参数或字段中。我不确定你的总体设计,所以这可能适用。在依赖注入中,你可以在你的代码中声明IAuditables应该使用UserAudit来创建,虽然这需要比简单调用“new IAuditable”更多的连接工作。

5

一种方法是使用泛型。

一旦您有一个实现I接口并具有公共的T类型,且无参数构造函数,您就可以创建T的实例:

public void Create<T>() where T : IAudit, new()
{
     T instance = new T();
     // TODO: Your logic here to use T instance of IAudit
} 

我不知道你的代码架构或目标,但是你可以创建一个工厂方法来创建IAudit对象的实例,就像上面的一个。

0
如果您需要为接口创建实例,则可以创建一个名为FactoryClass()的公共类,其中包含所有接口方法。您可以使用以下代码:
public class FactoryClass  //FactoryClass with Interface named "IINterface2"
{
   public IInterface2 sample_display()   //sample_display() is a instance method for Interface
   {
       IInterface2 inter_object = null;   //assigning NULL for the interface object
       inter_object = new Class1();       //initialising the interface object to the class1()
       return inter_object;   //returning the interface object
   }
}

在 Main() 类中添加以下代码:
IInterface2 newinter; //creating object for interface in class main()
FactoryClass factoryobj=new FactoryClass();  // creating object for factoryclass

在构造函数中添加以下内容:
newinter=factoryobj.sample_display() // initialisingg the interface object with the instance method of factoryobj of FACTORY CLASS.

您可以使用以下代码调用该函数:
newinter.display() //display() is the method in the interface.

0
你可以在作用域之外创建一个静态的接口变量,然后在代码中使用它。
static IRequestValidator ir;


static void Main(string[] args)...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接