По this article on Code Project:
Если вызов метода не удается или бизнес-логику проверки не удается, компонент .NET, как ожидается, вызовет исключение. Это исключение обычно имеет сбой HRESULT, присвоенный ему, и связанное с ним описание ошибки . CCW извлекает данные, такие как Код ошибки, Сообщение об ошибке и т. Д. Из .NET Exception и предоставляет эти данные в форме, которая может быть использована COM-клиентом.
Emphasis mine.
Итак, что мы можем проверить, чтобы узнать, установлено ли частное поле. Если это было, выбросьте исключение.
private string message;
public string Message {
get { return message; }
set
{
if (message != null)
{
throw new ReadOnlyPropertyException("Class1.Message can not be changed once it is set.");
}
message = value;
}
}
Потребляя это из следующего VB6/VBA код
Dim cls As New Rubberduck_SourceControl.Class1
cls.Message = "Hello"
Debug.Print cls.Message
cls.Message = "Goodbye" 'we expect a read only error here
Debug.Print cls.Message
приводит к ошибке поднимается.
Эффективно делает свойство только для чтения, как только он был установлен.
Но это приводит к тому, что клиент испытывает ошибки во время выполнения. Решением здесь является создание фабрики класса, предложенной @Hans Passant.
Понимание философии COM важно. COM предоставляет фабрику классов для создания объектов, но не поддерживает передачу произвольных аргументов. Вот почему вам всегда нужен конструктор по умолчанию. Ну, не проблема, просто создайте свой собственный завод. Скройте класс1 и напишите класс Class1Factory. С помощью метода CreateClass1(), который возвращает _Class1.Он может принимать любые аргументы, которые вам нужны.
Итак, я реализовал класс так, как я хотел первоначально. (С конструктором не по умолчанию и private set
собственности. Важно отметить, что интерфейс имеет только get
для свойства.
[Guid("B1E17DF6-9578-4D24-B578-9C70979E2F05")]
public interface _Class1
{
[DispId(2)]
string Message { get; }
[DispId(1)]
string TestingAMethod();
}
[Guid("197A7A57-E59F-41C9-82C8-A2F051ABA53C")]
[ProgId("Project.Class1")]
[ClassInterface(ClassInterfaceType.None)]
public class Class1 : _Class1
{
public string Message { get; private set; }
public Class1(string message)
{
this.Message = message;
}
public string TestingAMethod()
{
return "Hello World";
}
}
Затем я создал класс завод, который делает иметь конструктор по умолчанию и принимает в Те же аргументы, как конструктор Class1
«s.
[Guid("98F2287A-1DA3-4CC2-B808-19C0BE976C08")]
public interface _ClassFactory
{
Class1 CreateClass1(string message);
}
[Guid("C7546E1F-E1DB-423B-894C-CB19607972F5")]
[ProgId("Project.ClassFactory")]
[ClassInterface(ClassInterfaceType.None)]
public class ClassFactory : _ClassFactory
{
public Class1 CreateClass1(string message)
{
return new Class1(message);
}
}
Итак, теперь, если клиент пытается установить Message
свойство на всех, он получает время компиляции ошибка.
Понимание философии COM имеет важное значение. COM предоставляет фабрику классов для создания объектов, но не поддерживает передачу произвольных аргументов. Вот почему вам всегда нужен конструктор по умолчанию. Ну, не проблема, просто создайте свой собственный завод. Скройте класс1 и напишите класс Class1Factory. С помощью метода CreateClass1(), который возвращает _Class1. Он может принимать любые аргументы, которые вам нужны. –
Вы хотите создать завод на стороне клиента @HansPassant? – RubberDuck
Нет, на вашем сервере. –