Создание экземпляра интерфейса

У меня определены следующие интерфейсы:

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

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

Интерфейс IAuditable говорит, для каких классов у меня будет Audit для. Интерфейс IAudit является фактическим 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 сверху), я хотел бы иметь возможность создавать intance IAudit (UserAdit сверху) путем подачи объекта IAuditable в конструктор, В идеале у меня было бы что-то вроде:

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

Я уверен, что это шаблон дизайна, который у многих был раньше, но я не могу опустить его в голову. Я был бы очень признателен, если бы кто-нибудь мог показать мне, как это может быть достигнуто.

Ответы

Ответ 1

Нет, где в коде он определяет, какой IAudit относится к IAuditable Я не могу указать, что интерфейс IAudit должен иметь конструктор, который принимает IAuditable

Вы можете исправить эти два, добавив функцию CreateAudit() к вашему IAuditable. Затем вы получите IAudit, созданный с помощью IAuditable. В качестве бонуса, если вы хотите сохранить ссылку на IAudit в IAuditable (или наоборот), чтобы вы могли связать их друг с другом, довольно легко реализовать класс реализации. Вы также можете добавить GetAuditable() в IAudit, чтобы получить IAuditable, из которого он был создан, например.

Простая реализация будет выглядеть так (в классе, реализующем IAuditable):

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

Ответ 2

Вы не можете создать экземпляр интерфейса

Правильно. Вы создаете экземпляр объекта, реализующего интерфейс:

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

Правильно, вы не можете. См. здесь. Вам нужно создать такой конструктор для исполнителей.

Ответ 3

Один из способов - использование дженериков.

Как только у вас есть тип T, который реализует интерфейс я и имеет открытый конструктор без параметров, вы можете создать экземпляр T:

public void Create<T> where T : IAudit, new()
{
     T instance = new T();
     // TODO: Your logic using such T instance of IAudit implementation
} 

Я не знаю вашу архитектуру или цель кода, но вы можете создать метод factory, подобный приведенному выше, для создания экземпляров объектов IAudit.

Ответ 4

Очевидно, вы не можете создать экземпляр интерфейса, но если вы действительно пытались создать экземпляр прошедшего в классе, вы могли бы сделать это:

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

Вам нужно знать, какой конкретный класс построить, и в вашем примере единственным вариантом является myObject.

В качестве альтернативы вы можете исследовать что-то под названием "Dependancy Injection", которое позволяет вам указать, какой тип конкретного класса "вводить" в параметры, вызывающие интерфейсы в конструкторах или в полях. Я не уверен, что ваш общий дизайн, так что это может быть применимо. В Injection Dependancy вы можете указать в своем коде. IAuditables должен быть создан с использованием UserAudit, хотя есть немного больше подключений, чем просто вызов "new IAuditable"

Ответ 5

Если вам нужно создать экземпляр для интерфейса, вы можете создать открытый класс с именем FactoryClass(), который содержит весь метод Interfaces. вы можете использовать следующий код:

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.