Создание экземпляра интерфейса - PullRequest
17 голосов
/ 19 августа 2011

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

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 сверху), я хотел бы иметь возможность создать экземпляр 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

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

Ответы [ 5 ]

16 голосов
/ 19 августа 2011

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

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

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

public IAudit CreateAudit()
{
    UserAudit u = new UserAudit(UserName);
    return u;
}
15 голосов
/ 19 августа 2011

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

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

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

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

4 голосов
/ 19 августа 2011

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

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

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

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

4 голосов
/ 19 августа 2011

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

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

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

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

0 голосов
/ 09 апреля 2013

Если вам нужно создать экземпляр для интерфейса, вы можете создать открытый класс с именем 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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...