Можно ли (ab) использовать CoClassAttribute, чтобы обеспечить реализацию по умолчанию для интерфейса? - PullRequest
4 голосов
/ 11 ноября 2011

Недавно я обнаружил, что можно "обновить" интерфейс в C # , украшая интерфейс с помощью CoClassAttribute, чтобы указать реализацию по умолчанию.

[ComImport, Guid("579A4F68-4E51-479A-A7AA-A4DDC4031F3F"), CoClass(typeof(FooImpl))]
public interface IFoo
{
    void Bar();
}

public class FooImpl : IFoo
{
    public void Bar() { }
}

...

// Constructs a FooImpl
IFoo foo = new IFoo();

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

У меня естьдва вопроса:

  1. Есть ли какие-то ошибки с этим?Я не эксперт по COM-взаимодействию, и я не знаю, окажет ли это какое-либо негативное влияние на POCO.Я не запускал никаких серьезных тестов, но IL для моего примера выглядит нормально (обычная newobj инструкция для FooImpl, а не вызовы Type.GetTypeFromCLSID и Activator.CreateInstance).

  2. Даже если это будет работать гладко, есть ли другие причины (скажем, с точки зрения разработки API), чтобы этого избежать?

Ответы [ 2 ]

2 голосов
/ 11 ноября 2011

Основная причина, по которой вам не следует этого делать, заключается в том, что вы запускаете управление жизненным циклом COM для экземпляра объекта, который ему не нужен. Теперь .NET нужно будет выполнить некоторое COM-взаимодействие, которое включает в себя обход стека безопасности, проверки потоков в квартирах и утилиты addref / release.

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

Вот что я делаю в своих библиотеках. Допустим, я хочу написать сервис регистрации (надуманный пример). У меня было бы два основных компонента:

MyStuff.Logging.Contracts - здесь я бы объявил интерфейс ILogger MyStuff.Logging - здесь я бы написал различные реализации журналирования, которые могут быть у меня, такие как FileLogger, DatabaseLogger и т. Д.

Тогда в моем приложении я бы использовал Ninject или Unity (контейнеры DI), чтобы связать ILogger с реализацией по умолчанию.

0 голосов
/ 11 ноября 2011

Используйте комментарии intelisense:

    /// <summary>
    /// Explain here all about interface
    /// </summary>

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

Конечно, некоторые устаревшие инструменты будут иметь проблемы с чтением ваших /// комментариев, но они также не смогут прочитать ваши атрибуты.

...