Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object must implement IConvertible (InvalidCastException) while casting to interface

I'm trying to cast an object of a certain type to an interface it implements using Convert.ChangeType(), however an InvalidCastException gets thrown because the object must implement IConvertible.

The types:

public IDocumentSet : IQueryable {}

public IDocumentSet<TDocument> : IDocumentSet, IQueryable<TDocument> {}

public XmlDocumentSet<TDocument> : IDocumentSet<TDocument> {}

Excerpt from code where the error happens:

private readonly ConcurrentDictionary<Type, IDocumentSet> _openDocumentSets = new ConcurrentDictionary<Type, IDocumentSet>();

public void Commit()
{
    if (_isDisposed)
        throw new ObjectDisposedException(nameof(IDocumentStore));

    if (!_openDocumentSets.Any())
        return;

    foreach (var openDocumentSet in _openDocumentSets)
    {
        var documentType    = openDocumentSet.Key;
        var documentSet     = openDocumentSet.Value;

        var fileName        = GetDocumentSetFileName(documentType);
        var documentSetPath = Path.Combine(FolderPath, fileName);

        using (var stream = new FileStream(documentSetPath, FileMode.Create, FileAccess.Write))
        using (var writer = new StreamWriter(stream))
        {
            var documentSetType     = typeof (IDocumentSet<>).MakeGenericType(documentType);
            var writeMethod         = typeof (FileSystemDocumentStoreBase)
                                        .GetMethod(nameof(WriteDocumentSet), BindingFlags.Instance | BindingFlags.NonPublic)
                                        .MakeGenericMethod(documentSetType);
            var genericDocumentSet  = Convert.ChangeType(documentSet, documentSetType); <-------

            writeMethod.Invoke(this, new[] {writer, genericDocumentSet});
        }
    }
}

Now, I'm failing to understand why exactly this happens (as XmlDocumentSet is not a value type) and XmlDocumentSet<'1> implements IDocumentSet<'1>. Am I missing something? Or is there an easier way to achieve what I'm doing?

like image 257
artganify Avatar asked Sep 16 '16 11:09

artganify


People also ask

How do you solve an object must implement IConvertible?

Solution 2you have to implement IConvertable on the object because Covert. ChangeType() expects IConvertable object. So Convert object knows how to convert given object to the type that you need - even it is the same type.

What is IConvertible interface in C#?

The IConvertible interface allows conversion of an object to basic data types and allows the conversion methods in the Convert class to use that object. When implementing the IConvertible interface, create your own type-specific methods for each of the supplied conversion methods.


1 Answers

The IConvertible interface is designed to allow a class to safely convert itself to another Type. The Convert.ChangeType call uses that interface to safely convert one type to another.

If you do not know the Types at compile time then you will be forced to attempt a runtime cast. This is discussed in a very similar question here Convert variable to type only known at run-time?.

like image 139
PhillipH Avatar answered Sep 20 '22 22:09

PhillipH