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?
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.
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.
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?.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With