-2

CS1061 'object' does not contain a definition for 'Id'

public static async Task RemoveItem<T>(object obj) where T : class, new()
{
    if (obj == null || db == null)
        return;

    obj = obj as T;

    await db.DeleteAsync<T>(obj.Id); // error
}

Is this possible to solve or have I reached the edge?

user3772108
  • 854
  • 2
  • 14
  • 32

1 Answers1

-2

IMPORTANT: That question is marked duplicate and already closed. Nevertheless I want to share my original solution and than the result thanks to the comments.

While typing I've found the solution out :-) Thanks to Test if a property is available on a dynamic variable

public static async Task RemoveItem<T>(object obj) where T : class, new()
{
    if (obj == null || db == null)
        return;

    dynamic objA = obj as T;

    try
    {
        int id = objA.Id; // Check if property exists
        await db.DeleteAsync<T>(id);
    }
    catch (Exception)
    {
        throw;
    }
}

EDIT after comments:

public static async Task RemoveItem<T>(object obj) where T : class, IDatabaseEntity, new()
{
    if (obj == null || db == null)
        return;

    var entity = obj as IDatabaseEntity;
    await db.DeleteAsync<T>(entity.Id);
}
user3772108
  • 854
  • 2
  • 14
  • 32
  • 1
    Why are you catching an exception only to rethrow it? – Jon Skeet Jul 19 '21 at 15:59
  • 3
    Although your approach works I'd recommend to think about using an Interface on your `T` type. `where T: class, new(), IDatabaseEntity` .`IDatabaseEntity` defines a public property `Id` and all your database entities should inherit from it. Then you can change your input parameter to `T obj`. Using dynamics is always dangerous and I'd only use them as a last resort - they open vectors for injection attacks and all kinds of bugs and unexpected behavior. – Christoph Sonntag Jul 19 '21 at 16:11
  • Thanks for your comments guys. This is the feedback I am searching for to improve. :-) – user3772108 Jul 19 '21 at 16:13
  • 1
    P.S.: I think [this answer](https://stackoverflow.com/a/32817143/3085985) will give you some more insights about dynamics. – Christoph Sonntag Jul 19 '21 at 16:14
  • Thanks @Compufreak I will check that out. :-) – user3772108 Jul 19 '21 at 16:20
  • @JonSkeet as answer to your question: I am playing around with Xamarin and I use DisplayAlert to show the user when an error happens. But you are right, I can catch that outside the method. – user3772108 Jul 19 '21 at 17:57
  • "I've updated the code as Jon Skeet and Compufreak suggested." Not really - you've still catch a try/catch block that seems pointless to me. – Jon Skeet Jul 19 '21 at 17:57
  • Additionally, if you're going to constrain `T` to implement `IDatabaseEntity`, why is this method generic at all? Why not just have `public static async Task RemoveItem(IDatabaseEntity entity)`? – Jon Skeet Jul 19 '21 at 17:58
  • @JonSkeet `db.DeleteAsync` presumably needs the actual type. – Servy Jul 19 '21 at 18:05
  • @Servy: Ah, possibly. Although in that case wouldn't it still make more sense to make it accept a `T` rather than just `object`? Or *at least* accept `IDatabaseEntity`? (There seems to be no point in leaving the parameter type as `object`.) – Jon Skeet Jul 19 '21 at 18:10
  • I also note that the original question is about anonymous types, and an anonymous type will never implement `IDatabaseEntity`, so I can't see how this answer would apply... – Jon Skeet Jul 19 '21 at 18:11