Reputation: 23
I have a small problem I can't seem to get working right. I currently have a list of IModelConverters like this:
public class ModelConverterList : List<IModelConverter<IDataCollection>>
{
}
And I am trying to add entries like this:
public static void AddModelConverter<T>(IModelConverter<T> converter)
where T: IDataCollection
{
CheckForSetup();
modelConverters.Add(converter);
}
CheckForSetup is a method checking if the list isn't null (along with some other unrelevant checks). This is the interface I want to cast to:
public interface IModelConverter<in T>: IConverter where T: IDataCollection
{
ResponseData Activate(T documents, ServiceContext services, bool overrideIfNeeded = false);
bool ContainsFile(T document, ServiceContext services);
}
However, it doesn't want to cast to this interface. I tried casting it to IModelConverter<T>
and IModelConverter<IDataCollection>
The object I want to add has an abstract class that uses the interface, could this be why it isn't working?
I also thought about multiple references to it, but it doesn't seem like that's the case.
EDIT:
The error I get in the editor is this: "Argument 1: cannot convert from 'Extensions.Abstractions.Interfaces.IModelConverter' to 'Extensions.Abstractions.Interfaces.IModelConverter'"
And the class I want to add is this:
public class LanguageConverter : DocumentConverterCreatorBase<LanguageCollection>
{
protected override void ActivateDocument(LanguageCollection collection, ServiceContext services, bool overrideIfNeeded)
{
ILocalizationService fs = services.LocalizationService;
foreach (LanguageType language in collection.List)
{
if (fs.GetLanguageByIsoCode(language.CultureAlias) != null && overrideIfNeeded)
fs.Delete(fs.GetLanguageByIsoCode(language.CultureAlias));
if (fs.GetLanguageByIsoCode(language.CultureAlias) == null)
fs.Save(language.Construct(services));
}
}
public override bool ContainsFile(LanguageCollection document, ServiceContext services)
{
ILocalizationService ls = services.LocalizationService;
foreach (LanguageType item in document.List)
{
if (ls.GetLanguageByIsoCode(item.CultureAlias) == null)
return false;
}
return true;
}
}
And the abstract class is this:
public abstract class DocumentConverterCreatorBase<T>: IAssetConverter, IModelConverter<T>, IModelCreator where T : IDataCollection
The abstract class has two abstract methods for the methods in the interface.
The IDataCollection is nothing but a list of data. The interface is as follows:
public interface IDataCollection
{
int GetCount();
}
Upvotes: 0
Views: 2127
Reputation: 117027
The problem you're seeing is one of co-variance.
If you have these type definitions:
public class ModelConverterList : List<IModelConverter<IDataCollection>> { }
public interface IModelConverter<in T> : IConverter where T : IDataCollection { }
public interface IDataCollection { }
public interface IConverter { }
...then with this code:
private static ModelConverterList modelConverters = new ModelConverterList();
public static void AddModelConverter<T>(IModelConverter<T> converter) where T : IDataCollection
{
modelConverters.Add(converter);
}
...you get the following error:
CS1503 Argument 1: cannot convert from 'IModelConverter<T>' to 'IModelConverter<UserQuery.IDataCollection>'
Even though we know that T
inherits from IDataCollection
, it isn't the same as saying that IModelConverter<T>
inherits from IModelConverter<IDataCollection>
- it doesn't. So there is no cast from IModelConverter<T>
to IModelConverter<IDataCollection>
.
This compiles:
public class ModelConverterList : List<IModelConverter<IDataCollection>> { }
public interface IModelConverter<out T> : IConverter where T : class, IDataCollection { }
public interface IDataCollection { }
public interface IConverter { }
private static ModelConverterList modelConverters = new ModelConverterList();
public static void AddModelConverter<T>(IModelConverter<T> converter) where T : class, IDataCollection
{
modelConverters.Add(converter);
}
But I've changed the definition of IModelConverter
from in T
to out T
and added a class
constraint.
Upvotes: 3