3

I have ClassLibrary (in visual studio 2010 C#) with a class Car:

[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("ClassLibrary1.Car")]
public class Car
{
    public Car()
    {
        Name = "";
        Parts = new List<string>();
    }

    public string Name { get; set; }

    public List<string> Parts { get; set; }
}

But when I use it in vb6 project: there is no property "Parts": https://i.sstatic.net/nMfEi.jpg

What can I do to make property List<> visible?

Of course, the file "AssemblyInfo.cs" contains:

[assembly: ComVisible(true)]

P.S. I really do not want to create for each List the class, like this:

public class Parts
{
    private List<string> _parts;

    public Parts()
    {
        _parts = new List<string>();
    }

    public void Add(string part)
    {
        _parts.Add(part);
    }

    public string GetAt(int index)
    {
        if (0 <= index && index < _parts.Count)
            return _parts[index];
        return "";
    }

    public void Clear()
    {
        _parts.Clear();
    }

    public int Count{ get{ return _parts.Count; } }
}

because there are too many.

2 Answers 2

3

COM does not support generic collections; you'll have to use an array or ArrayList instead:

[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("ClassLibrary1.Car")]
public class Car
{
    public Car()
    {
        Name = "";
        Parts = new string[];
    }

    public string Name { get; set; }

    public string[] Parts { get; set; }
}

If you want to use a List behind-the-scenes you could use a List<string> as a backing variable, then change the property accessors to translate the list to/from an array:

[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("ClassLibrary1.Car")]
public class Car
{

    private List<string> _Parts;

    public Car()
    {
        Name = "";
        _Parts = new List<string>();
    }

    public string Name { get; set; }

    public string[] Parts 
    { 
        get
        {
            return _Parts.ToArray();
        } 
        set
        {
            _Parts = new List<string>(value);
        } 
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Out of interest, if you just inherit from the generic to make a concrete definition (ie class Parts : List<Part>) and add the attributes, would that be acceptable for Com Visibility?
I added class: [ClassInterface(ClassInterfaceType.AutoDual)] [ProgId("Modem_TAO_Well3DView.Parts")] public class Parts : List<string> { public Parts() { MaxCount = 50; } public static int MAX_COUNT = 50; public int GetMaxCount() { return 50; } public int MaxCount { get; set; } } But nothing is visible (properties, fields, etc). Perhaps you meant IList<Part>
I hope - there is a class attribute that allows access to the property List
1

I did not want to do so, but had:

[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("ClassLibrary1.Car")]
public class Car
{
    public Car()
    {
        Name = "";
        Parts = new Parts();
    }

    public string Name { get; set; }

    public Parts Parts { get; set; }
}

[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("ClassLibrary1.Parts")]
public class Parts : IList<string>
{
    private List<string> _parts;

    public Parts()
    {
        _parts = new List<string>();
    }

    #region IList<string> Members

    public int IndexOf(string item)
    {
        return _parts.IndexOf(item);
    }

    public void Insert(int index, string item)
    {
        _parts.Insert(index, item);
    }

    public void RemoveAt(int index)
    {
        _parts.RemoveAt(index);
    }

    public string this[int index]
    {
        get
        {
            return _parts[index];
        }
        set
        {
            _parts[index] = value;
        }
    }

    #endregion

    #region ICollection<string> Members

    public void Add(string item)
    {
        _parts.Add(item);
    }

    public void Clear()
    {
        _parts.Clear();
    }

    public bool Contains(string item)
    {
        return _parts.Contains(item);
    }

    public void CopyTo(string[] array, int arrayIndex)
    {
        _parts.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return _parts.Count; }
    }

    public bool Remove(string item)
    {
        return _parts.Remove(item);
    }

    #endregion

    #region ICollection<string> Members


    public bool IsReadOnly
    {
        get { throw new NotImplementedException(); }
    }

    #endregion

    #region IEnumerable<string> Members

    public IEnumerator<string> GetEnumerator()
    {
        throw new NotImplementedException();
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    #endregion
}

In vb6:

Option Explicit
Dim car As New ClassLibrary1.car
Dim parts As New ClassLibrary1.parts

Private Sub Form_Load()

    parts.Add "wheel"
    parts.Add "door"
    parts.Add "hood"
    parts.Add "trunk"

    car.Name = "GAS-24"
    Set car.parts = parts
    car.parts.RemoveAt (0)
End Sub

Drawback of this approach is a lot of code:(

Let me know, if anyone knows something like this:

//**[MakeVisibleListInVB6]**
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("ClassLibrary1.Car")]
public class Car
{
    public Car()
    {
        Name = "";
        Parts = new Parts();
    }

    public string Name { get; set; }

    public List<string> Parts { get; set; }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.