Why Cannot I Cast My Com Object to the Interface It Implements in C#

Why I cannot cast an object to an interface it is implementing?

I think you should take a look at my response to this question, it explains you case Interface with generic object of the interface type

By the way I suggest you make changes to you GetIt Function like that :

public static IASet<T> GetIt<T>() 
where T : IItem
{
ASet a = new ASet();
a.Collection = new HashSet<OneItem>();
a.Collection.Add(new OneItem() { Name = "one" });
a.Collection.Add(new OneItem() { Name = "two" });
//for test :
foreach (var i in a.Collection)
{
Console.WriteLine(i.Name);
}

/*Error 1 Cannot implicitly convert type 'ConsoleApplication2.Program.ASet'
* to 'ConsoleApplication2.IASet<ConsoleApplication2.IItem>'. An explicit
* conversion exists (are you missing a cast?)
*/
//return a;

/*Unable to cast object of type 'ASet' to type
* 'ConsoleApplication2.IASet`1[ConsoleApplication2.IItem]'.
*/
return (IASet<T>)a;
}

and then you need to call it like that:

  IASet<OneItem> aset = GetIt<OneItem>();
foreach (IItem i in aset.Collection)
Console.WriteLine(i.Name);

if you want more details you have to explain your requirement more.

Unable to cast object to interface it implements - cast interface to another interface

If you post your question correctly, it works fine:

class Program
{
static void Main()
{
Call(new Car());

Call(new MotorBike());
}

public static void Call(IVehicles vehicle)
{
Object someIrrelevantObject = vehicle.SomeValue;
//here my change begins
IPersonalVehicles personalVehicle = (IPersonalVehicles)vehicle;
long somePersonalValue = personalVehicle.SomePersonalValue;
}

}

public interface IVehicles

{
Object SomeValue { get; }
}

public interface IPersonalVehicles

{
long SomePersonalValue { get; }
}

public class Car : IVehicles, IPersonalVehicles
{
public long SomePersonalValue => long.MinValue;

public object SomeValue => "car value";
}

public class MotorBike : IVehicles, IPersonalVehicles
{
public long SomePersonalValue => long.MaxValue;

public object SomeValue => "motorbike value";
}

Why cannot I cast my COM object to the interface it implements in C#?

So, the problem was that my DLL with IDiagnostics interface was generated from a TLB, and that TLB never got registered.

Since the DLL was imported from the TLB, RegAsm.exe refuses to register the library. So I used the regtlibv12.exe tool to register the TLB itself:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\regtlibv12.exe "$(ProjectDir)\lib\Diagnostics.tlb"

Then everything magically started to work.

Since regtlibv12 is not a supported tool, I still don't know how to do this properly.

C# - Error casting object to interface

Shared projects compile their source files directly into each project that references them.

Therefore, you have two ICrawler interfaces, one in each assembly, which are not the same type (even though they're identical).

You're trying to cast the new instance to the copy of the interface that it doesn't implement; you can't do that.

You should use a normal Class Library, not a Shared Project.

Unable to cast 2 objects although they share same interface

You can use json for this. We do this all the time to cast DataTable into a model.

You Serialize the first model and Deserialize it into the other one.
Doing it this way, only the fields that are in common are touched.

        var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
string serializedObject = JsonConvert.SerializeObject(A, deserializeSettings);
B b = JsonConvert.DeserializeObject<B>(serializedObject);

foreach loop can not cast type to the interface it implements

I solved this by adding another level of indirection. Having followed advice from @PeterDuniho, I broke apart the INotification<TMessage> interface in to two separate interfaces. By adding the new INotificationProcessor interface, I can change my collection of listeners from an ISubscription to an INotificationProcessor and then iterate over my collection of listeners as an INotificationProcessor.

public interface ISubscription
{
void Unsubscribe();
}

public interface INotification<TMessageType> : ISubscription where TMessageType : class, IMessage
{
void Register(Action<TMessageType, ISubscription> callback);
}

public interface INotificationProcessor
{
void ProcessMessage(IMessage message);
}

The INotificationProcessor implementation, implements both INotificationProcessor and INotification<TMessageType>. This allows the Notification class below to cast the IMessage provided in to the appropriate generic type for publication.

internal class Notification<TMessage> : INotificationProcessor, INotification<TMessage> where TMessage : class, IMessage
{
private Action<TMessage, ISubscription> callback;

public void Register(Action<TMessage, ISubscription> callbackMethod)
{
this.callback = callbackMethod;
}

public void Unsubscribe()
{
this.callback = null;
}

public void ProcessMessage(IMessage message)
{
// I can now cast my IMessage to T internally. This lets
// subscribers use this and not worry about handling the cast themselves.
this.callback(message as TMessage, this);
}
}

My NotificationManager can now hold a collection of INotificationProcessor types instead of ISubscription and invoke the ProcessMessage(IMessage) method regardless if what comes in to it is an IMessage or a ServerMessage.

public class NotificationManager
{
private ConcurrentDictionary<Type, List<INotificationProcessor>> listeners =
new ConcurrentDictionary<Type, List<INotificationProcessor>>();

public ISubscription Subscribe<TMessageType>(Action<TMessageType, ISubscription> callback) where TMessageType : class, IMessage
{
Type messageType = typeof(TMessageType);

// Create our key if it doesn't exist along with an empty collection as the value.
if (!listeners.ContainsKey(messageType))
{
listeners.TryAdd(messageType, new List<INotificationProcessor>());
}

// Add our notification to our listener collection so we can publish to it later, then return it.
var handler = new Notification<TMessageType>();
handler.Register(callback);

List<INotificationProcessor> subscribers = listeners[messageType];
lock (subscribers)
{
subscribers.Add(handler);
}

return handler;
}

public void Publish<T>(T message) where T : class, IMessage
{
Type messageType = message.GetType();
if (!listeners.ContainsKey(messageType))
{
return;
}

// Exception is thrown here due to variance issues.
foreach (INotificationProcessor handler in listeners[messageType])
{
handler.ProcessMessage(message);
}
}
}

The original app example now works without issue.

class Program
{
static void Main(string[] args)
{
var notificationManager = new NotificationManager();
ISubscription subscription = notificationManager.Subscribe<ServerMessage>(
(message, sub) => Console.WriteLine(message.Content));

notificationManager.Publish(new ServerMessage("This works"));
IMessage newMessage = MessageFactoryMethod("This works without issue.");
notificationManager.Publish(newMessage);

Console.ReadKey();
}

private static IMessage MessageFactoryMethod(string content)
{
return new ServerMessage(content);
}
}

Thanks everyone for the help.

Force cast a COM object to an interface

You can't cast an object to an interface it does not implement. So you can't create your own interface and try to cast an object to it.

You can try using dynamic instead. You'll loose IntelliSense support, but I think you can live with this.

C# Can't cast to interface even though it inherits it

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.

Why can't I cast this interface to a concrete class?

The reason is that newItem can be any type that implements IApiDataWithProperties, so compiler can't guarantee that it's type is convertible to Event. Even if you check it using is operator it means nothing to the compiler. As a workaround you can use double cast:

((Event)(object)newItem).Log();

Even though this works, it doesn't mean you should use it. You shouldn't check the type in a generic method. Instead try using polymorphism, add the Log method to IApiDataWithProperties or some other interface and implement it in your types. Then have another constraint for that interface, then you can call the method without needing a cast.



Related Topics



Leave a reply



Submit