简体   繁体   中英

General function to return Id

In my project i've written my own mappers, and there's a lot of places where I'm doing things like tbl.Type != null ? tbl.Type.Id : 0 tbl.Type != null ? tbl.Type.Id : 0 to return the id of referenced objects. Because this is occuring so many times, I'm trying to make a small function that does this check for me, no matter the type of object I pass.

I was thinking along the lines of

public static int returnId(object input)
{
    if(input != null && input.Id != null)
    {
        return input.Id;
    }
    return 0;
}

or maybe using generic type <T> .

Currently this function throws errors because object doesn't contain a definition for .Id . I've been googling around for a few hours now, and start to wonder if what I'm looking for is even possible.

Any help and ideas are welcome and much appreciated!

All inputs should implement IId interface:

public static int returnId(IId input)
{
    if(input != null && input.Id != null)
    {
        return input.Id;
    }
    return 0;
}

Or via reflection:

public static int returnId(object input)
{        
    if(input != null)
    {
        var Id = input.GetType().GetProperty("Id").GetValue(input);
        if(Id != null)
            return ((int?)Id).Value;
    }
    return 0;
}

You have two options:

1: Use dynamic instead of object :

public static int returnId(dynamic input)
{
    if(input != null && input.Id != null)
    {
        return input.Id;
    }
    return 0;
}

2: Have all your classes inherit from an interface that defines id :

public static int returnId(IId input)
{
    if(input != null && input.Id != null)
    {
        return input.Id;
    }
    return 0;
}

public interface IId
{
   int Id {get; set;}
}

The 2nd option should have better performance, because dynamic requires the operation to be resolved at runtime.

What you're trying to do is not feasible in the general case. If you want to be able to retrieve an object's Id you need to ensure that property Id exists in every type you would use with your method.

In most cases the best option would be to follow Slava's original suggestion, namely (with minor enhancements)

public interface IId
{
    int Id {get;}
}

public static int returnId<T>(T input) where T : IId
{
    return input != null ? input.Id : 0;
}

Using dynamic and reflection (eg input.GetType().GetProperty("Id").GetValue(input)) would have a similar effect, but 1) it provides no compile-time guarantees - all validation is done at runtime and will fail if the type has not property named "Id"; 2) runtime logic has negative impact on performance, which would be visible during intense usage.

Inheritance, as suggested by @hofmeister is an option only when you only need to apply this method to types defined by yourself, not any third-party classes.

You could use inheritance and implement the Id property for each of your class. Something like this:

public abstract class ObjectId
{
    // Or as auto-propert `public virtual int Id { get; private set; }`.
    public abstract int Id { get; }
}

public class ObjectImpl : ObjectId
{
    public override int Id
    {
        get { return 0; }
    }
}

In addition to this implementation, you can define a default value (as virtual property) for your base class. As a result, not every class has to override the property Id .

With this implementation, you can pass the ObjectId as input type to your function and return 0 if it's null .

public static int returnId(ObjectId input)
{
    return (input != null) ? input.Id : 0; // input.Id will never be null.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM