我的 C# COM 库无法正常工作;无法实例化类并且方法显示为属性

发布于 2024-11-29 00:47:41 字数 6005 浏览 1 评论 0原文

我正在用 C# 编写一个 COM DLL 来处理 X.12 格式文档的导入和导出,因此我可以在 Access 数据库和自定义程序中使用它来处理我公司的 EDI。我已经编译了一个 DLL,但结果令人失望,我想知道我是否遗漏了一些东西; COM“从头开始”对我来说是新领域(我之前为 Excel 制作过功能区,但向导处理了所有这些)。

我已阅读MSDN 上的这篇文章并发现这个问题在这里 编译和注册我的 DLL 和 TLB。这是我的 X12Segment 类的骨架和 COM 可见性的接口:

using System;
using System.Collections;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace X12
{
    [Guid("28A76274-05EE-45B2-A8EF-ADD5A5B351DE"),
    ComVisible(true)]
    public interface IX12Segment
    {
        [DispId(1)]
        string SegmentType { get; set; }
        [DispId(2)]
        string[] Fields { get; set; }
        [DispId(3)]
        char FieldDelimiter { get; set; }
        [DispId(4)]
        char SegmentDelimiter { get; set; }
        [DispId(5)]
        string ToString(char sep, char eol);
        [DispId(6)]
        string ToString();
        [DispId(7)]
        Type GetFieldEnum();
    }

    [Guid("B321599A-E5EC-4510-A021-E9A8B4D6293E"),
    ClassInterface(ClassInterfaceType.None),
    ComVisible(true)]
    public class X12Segment : IX12Segment
    {
        private string _type;

        protected ArrayList _fields;
        protected short _minFields = -1;
        protected short _maxFields = -1;
        protected short[][] _fieldSizes = { new short[] { -1, -1 } };
        protected char _sep;
        protected char _eol;

        public enum Field { }

        /// <summary>
        /// Creates a new X.12 segment of the supplied type,
        /// optionally with a supplied number of fields or
        /// values.
        /// </summary>
        /// <param name="segType">The type of segment (eg "ISA", "GS")</param>
        /// <param name="fields">Each string is a field
        /// within the segment</param>
        public X12Segment(string segType, params string[] fields)
            : this(segType)
        {
            //Do cool stuff
        }

        /// <summary>
        /// Creates a new X.12 segment from a string.
        /// </summary>
        /// <param name="segType">The type of segment (eg "ISA", "GS")</param>
        /// <param name="segment">The string to parse</param>
        public X12Segment(string segType, string segment)
            : this(segType)
        {
            //Do cool stuff
        }

        /// <summary>
        /// Creates a new X.12 segment of the supplied type,
        /// optionally with a supplied number of fields or
        /// values.
        /// </summary>
        /// <param name="segType">The type of segment (eg "ISA", "GS")</param>
        /// <param name="fieldCount">The number of fields
        /// in this segment</param>
        public X12Segment(string segType, int fieldCount) : this(segType)
        {
            //Do cool stuff
        }

        /// <summary>
        /// Creates a new X.12 segment of the supplied type,
        /// optionally with a supplied number of fields or
        /// values.
        /// </summary>
        /// <param name="segType">The type of segment (eg "ISA", "GS")</param>
        public X12Segment(string segType) : this()
        {
            //Do cool stuff
        }

        public X12Segment()
        {
            //Do cool stuff
        }

        /// <summary>
        /// Gets or sets the segment type.
        /// </summary>
        public string SegmentType
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets all of the fields in the segment,
        /// in the form of an array of strings.
        /// </summary>
        public string[] Fields
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the character used to seperate fields in the segment.
        /// </summary>
        public char FieldDelimiter
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the character denoting the end of the segment.
        /// </summary>
        public char SegmentDelimiter
        {
            get;
            set;
        }

        /// <summary>
        /// Generates an X.12 formatted segment.
        /// </summary>
        /// <param name="sep">The field delimiter to use.</param>
        /// <param name="eol">The segment delimiter to use.</param>
        /// <returns>An X.12 formatted string.</returns>
        public string ToString(char sep, char eol)
        {
            //Do cool stuff
        }

        /// <summary>
        /// Generates an X.12 formatted segment.
        /// </summary>
        /// <returns>An X.12 formatted string.</returns>
        public override string ToString()
        {
            //Do cool stuff
        }

        /// <summary>
        /// Returns the Type associated with the Field enumeration of this object.
        /// </summary>
        /// <returns>A System.Type of this object's Field enumeration.</returns>
        public virtual Type GetFieldEnum()
        {
            //Do cool stuff
        }
    }
}

现在,当我打开 VBA 并添加引用时,该类会显示在 IntelliSense 中。但是,当我用 X12Segment 类型调暗变量,然后放入点运算符时,弹出的 IntelliSense 窗口显示 ToString() 是一个属性,而不是一个方法。此外,ToString 的重载显示为 ToString_2。当我尝试 Set seg = New X12Segment 时,VBA 告诉我 New 关键字的使用无效。

我在这里缺少什么?

更新

我已经根据下面的评论和答案修改了我的代码,并且我有针对 New 不起作用以及我的 ToString 重载在 IntelliSense 中显得奇怪的解决方案。然而,一个新问题出现了;尝试访问字段给我错误。 seg.Fields = someStringArray 出现错误,提示“函数或接口标记为受限,或者函数使用 Visual Basic 不支持的自动化类型”。

I'm writing a COM DLL in C# to handle the import and export of X.12 format documents, so I would be able to use it in an Access database and a custom program for handling EDI with my company. I've gotten a DLL to compile but with disappointing results, and I'm wondering if I'm missing something; COM "from scratch" is new ground to me (I've made a ribbon for Excel before but a wizard handled all of that).

I've read this article on MSDN and came across this question here to get my DLL and TLB to compile and register. This is the skeleton of my X12Segment class and the interface for COM visibility:

using System;
using System.Collections;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace X12
{
    [Guid("28A76274-05EE-45B2-A8EF-ADD5A5B351DE"),
    ComVisible(true)]
    public interface IX12Segment
    {
        [DispId(1)]
        string SegmentType { get; set; }
        [DispId(2)]
        string[] Fields { get; set; }
        [DispId(3)]
        char FieldDelimiter { get; set; }
        [DispId(4)]
        char SegmentDelimiter { get; set; }
        [DispId(5)]
        string ToString(char sep, char eol);
        [DispId(6)]
        string ToString();
        [DispId(7)]
        Type GetFieldEnum();
    }

    [Guid("B321599A-E5EC-4510-A021-E9A8B4D6293E"),
    ClassInterface(ClassInterfaceType.None),
    ComVisible(true)]
    public class X12Segment : IX12Segment
    {
        private string _type;

        protected ArrayList _fields;
        protected short _minFields = -1;
        protected short _maxFields = -1;
        protected short[][] _fieldSizes = { new short[] { -1, -1 } };
        protected char _sep;
        protected char _eol;

        public enum Field { }

        /// <summary>
        /// Creates a new X.12 segment of the supplied type,
        /// optionally with a supplied number of fields or
        /// values.
        /// </summary>
        /// <param name="segType">The type of segment (eg "ISA", "GS")</param>
        /// <param name="fields">Each string is a field
        /// within the segment</param>
        public X12Segment(string segType, params string[] fields)
            : this(segType)
        {
            //Do cool stuff
        }

        /// <summary>
        /// Creates a new X.12 segment from a string.
        /// </summary>
        /// <param name="segType">The type of segment (eg "ISA", "GS")</param>
        /// <param name="segment">The string to parse</param>
        public X12Segment(string segType, string segment)
            : this(segType)
        {
            //Do cool stuff
        }

        /// <summary>
        /// Creates a new X.12 segment of the supplied type,
        /// optionally with a supplied number of fields or
        /// values.
        /// </summary>
        /// <param name="segType">The type of segment (eg "ISA", "GS")</param>
        /// <param name="fieldCount">The number of fields
        /// in this segment</param>
        public X12Segment(string segType, int fieldCount) : this(segType)
        {
            //Do cool stuff
        }

        /// <summary>
        /// Creates a new X.12 segment of the supplied type,
        /// optionally with a supplied number of fields or
        /// values.
        /// </summary>
        /// <param name="segType">The type of segment (eg "ISA", "GS")</param>
        public X12Segment(string segType) : this()
        {
            //Do cool stuff
        }

        public X12Segment()
        {
            //Do cool stuff
        }

        /// <summary>
        /// Gets or sets the segment type.
        /// </summary>
        public string SegmentType
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets all of the fields in the segment,
        /// in the form of an array of strings.
        /// </summary>
        public string[] Fields
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the character used to seperate fields in the segment.
        /// </summary>
        public char FieldDelimiter
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the character denoting the end of the segment.
        /// </summary>
        public char SegmentDelimiter
        {
            get;
            set;
        }

        /// <summary>
        /// Generates an X.12 formatted segment.
        /// </summary>
        /// <param name="sep">The field delimiter to use.</param>
        /// <param name="eol">The segment delimiter to use.</param>
        /// <returns>An X.12 formatted string.</returns>
        public string ToString(char sep, char eol)
        {
            //Do cool stuff
        }

        /// <summary>
        /// Generates an X.12 formatted segment.
        /// </summary>
        /// <returns>An X.12 formatted string.</returns>
        public override string ToString()
        {
            //Do cool stuff
        }

        /// <summary>
        /// Returns the Type associated with the Field enumeration of this object.
        /// </summary>
        /// <returns>A System.Type of this object's Field enumeration.</returns>
        public virtual Type GetFieldEnum()
        {
            //Do cool stuff
        }
    }
}

Now, when I open up VBA and add the reference, the class shows up in IntelliSense. However, when I Dim a variable with the X12Segment type, then put in the dot operator, the IntelliSense window that pops up shows me that ToString() is a property, not a method. Also, ToString's overload shows up as ToString_2. When I attempt Set seg = New X12Segment, VBA tells me that it's an invalid use of the New keyword.

What am I missing here?

Update

I've revised my code as per the comments and answer below, and I have solutions for New not working and my ToString overload appearing funky in IntelliSense. A new problem arises, though; trying to access Fields gives me errors. seg.Fields = someStringArray gets me an error saying "Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

愁杀 2024-12-06 00:47:41

[ComVisible] 类必须具有无参数构造函数。 COM 没有将参数传递给构造函数的机制。您只提供了带有参数的构造函数,这就是 VBA 不允许您使用 New 关键字的原因。

COM 也不支持方法重载。您需要为这些方法指定不同的名称。如果您不这样做,类型库导出器将自动处理它。因此ToString_2()。

A [ComVisible] class must have a parameterless constructor. COM doesn't have a mechanism to pass arguments to a constructor. You provided only constructors that take arguments which is why VBA doesn't let you use the New keyword.

COM also doesn't support method overloading. You need to give the methods distinct names. If you don't then the type library exporter will take care of it automatically. Thus ToString_2().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文