简体   繁体   中英

Generic Interface type conversion issues

I have been battling with this bit of code for a while now and I am trying to get a solution as it is literally the last part before it goes to testing.

I have the following interfaces and classes (simplified to the relevant parts):

public interface ITagParent<T> where T : ITag
{
    List<TagAddOn<T>> TagCollection { get; set; }
}

public interface ITag
{
    int Id { get; set; }
    string Description { get; set; }
    TagGroup TagGroup { get; set; }
}

public class TagAddOn<T> : ViewModelBase where T : ITag
{
    private T _currentTag;
    public T CurrentTag
    {
        get { return _currentTag; }
        set { _currentTag = value; }
    }
}

public partial class Customer : ITagParent<CustomerTag>
{
    List<TagAddOn<CustomerTag>> _tagCollection;
    public List<TagAddOn<CustomerTag>> TagCollection
    {
        get { return _tagCollection; }
        set { _tagCollection = value; }
    }
}

public partial class CustomerTag : ITag
{
    public int Id { get; set; }
}

public class TagAddOnManager
{
    public static string GetTagCurrentValue(List<TagAddOn<ITag>> dataObjectAddOns)
    {
        // LOTS OF SNIPPING!
        return string.Empty;
    }
}

I am trying to use the GetTagCurrentValue method in the TagAddOnManager class like this:

string value = TagAddOnManager.GetTagCurrentValue(
    ((ITagParent<ITag>)gridCell.Row.Data).TagCollection));

Everything compiles fine, but errors when trying to cast gridCell.Row.Data to ITagParent<ITag> . I understand this is due to covarience and a workaround (if not a terribly safe one) is to mark T in the ITagParent interface with the out keyword, but that won't work as you can see it is used in the TagCollection property, which can't be read only.

I tried casting the above to ITagParent<CustomerTag> , but this fails at compile time with a 'cannot convert' error when trying to feed it into my GetTagCurrentValue method.

Another option I considered is using some base classes instead of the ITagParent interface, but that won't work as the Customer object already inherits from another base class, which can't be modified for this implementation.

I know I could just overload the GetTagCurrentValue method with List<TagAddOn<CustomerTag>> as the parameter type and all other variations, but that really seems like a 'I give up' solution. I could probably use reflection to get the desired results, but that would be unwieldy and not very efficient, especially considering this method could be called a lot in a particular process.

So does anyone have any suggestions?

Could you use something like that

public class TagAddOnManager
{
    public static string GetTagCurrentValue<TTag>(ITagParent<TTag> tagParent)
        where TTag : ITag
    {
        // Just an example.
        return tagParent.TagCollection.First().CurrentTag.Description;
    }
}

and use it like that?`

var value = TagAddOnManager.GetTagCurrentValue((Customer)CustomergridCell.Row.Data);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM