gpt4 book ai didi

c# - 如何创建向 COM 公开的只读属性?

转载 作者:行者123 更新时间:2023-11-30 13:56:26 25 4
gpt4 key购买 nike

我有一个 C# 类,我想通过 COM 将其公开给 VB6。问题是这需要有一个类的默认构造函数。因此,我必须向客户端公开 setter,以便可以设置这些属性。

例如:

[Guid("B1E17DF6-9578-4D24-B578-9C70979E2F05")]
public interface _Class1
{

[DispId(2)]
string Message { get; set; }

[DispId(1)]
string TestingAMethod();
}

[Guid("197A7A57-E59F-41C9-82C8-A2F051ABA53C")]
[ProgId("Project.Class1")]
[ClassInterface(ClassInterfaceType.None)]
public class Class1 : _Class1
{
public string Message { get; set; }

public Class1() { } //default constructor for COM

public Class1(string message)
{
this.Message = message;
}

public string TestingAMethod()
{
return "Hello World";
}
}

通常,我会将属性声明为:

public string Message { get; private set; }

但这显然行不通,因为 COM 不能使用接受参数的构造函数。

所以,问题是:

如何在不使用 private setreadonly 的情况下确保属性仅设置一次?

最佳答案

根据 this article on Code Project :

If the method call fails or business logic validation fails, the .NET component is expected to raise an exception. This exception usually has a failure HRESULT assigned to it and an Error description associated with it. The CCW gleans out details such as the Error Code, Error message etc. from the .NET Exception and provides these details in a form that can be consumed by the COM client.

强调我的。

所以,我们可以检查一下是否设置了私有(private)字段。如果是,则抛出异常。

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

导致出现错误。

vb error dialog

在设置属性后有效地将其设置为只读。


但这会导致客户端遇到运行时错误。这里的解决方案是创建一个类工厂作为 @Hans Passant建议。

Understanding the COM philosophy is important. COM provides a class factory to create objects but it doesn't support passing arbitrary arguments. Which is why you always need a default constructor. Well, no problem, just create your own factory. Hide Class1 and write a Class1Factory class. With a CreateClass1() method that returns _Class1. It can take any arguments you need.

所以,我按照我最初想要的方式实现了这个类。 (没有默认构造函数和 private set 属性。重要的是要注意该接口(interface)只有一个 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 的构造函数相同的参数。

[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 属性完全,它会得到一个编译时间 而是错误。

compile error: can't assign to read only property

关于c# - 如何创建向 COM 公开的只读属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28489915/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com