C# 检查传入接口参数的对象是否具有附加属性

C# 检查传入接口参数的对象是否具有附加属性,c#,C#,我有两个User类,User和TenantUser,它们实现了一个IUser接口: public interface IUser { int Id { get; set; } string Username { get; set; } string Email { get; set; } string FirstName { get; set; } string LastName { get; set; } } public

我有两个
User
类,
User
TenantUser
,它们实现了一个
IUser
接口:

public interface IUser
{
    int Id           { get; set; }
    string Username  { get; set; }
    string Email     { get; set; }
    string FirstName { get; set; }
    string LastName  { get; set; }
}
public class User : IUser
{
    public int Id           { get; set; }
    public string Username  { get; set; }
    public string Email     { get; set; }
    public string FirstName { get; set; }
    public string LastName  { get; set; }
}
public class TenantUser : IUser
{
    public int Id           { get; set; }
    public int TenantId     { get; set; }
    public string Username  { get; set; }
    public string Email     { get; set; }
    public string FirstName { get; set; }
    public string LastName  { get; set; }
}
唯一的区别是
TenantUser
有一个额外的属性:
TenantId

当我编写代码时,我会执行以下操作:

IUser user;

user = getAdminUser("username", "password");

if (user == null) 
{
    user = getTenantUser("username", "password");

    if (user == null) 
        return Unauthorized();
}

然后,当我继续我的代码时,我需要检查
TenantId
是否是用户对象上的属性,如果是,则获取值。这可能吗?

您可以将
TenantId
添加到另一个接口,并在
TenantUser
中实现它。然后尝试转换到该界面:

public interface IUser
{
    int Id           { get; set; }
    string Username  { get; set; }
    string Email     { get; set; }
    string FirstName { get; set; }
    string LastName  { get; set; }
}
public class User : IUser
{
    public int Id           { get; set; }
    public string Username  { get; set; }
    public string Email     { get; set; }
    public string FirstName { get; set; }
    public string LastName  { get; set; }
}
public class TenantUser : IUser
{
    public int Id           { get; set; }
    public int TenantId     { get; set; }
    public string Username  { get; set; }
    public string Email     { get; set; }
    public string FirstName { get; set; }
    public string LastName  { get; set; }
}
鉴于:

interface ITenant
{
    int TenantId { get; set; }
}

public class TenantUser : IUser, ITenant
{ ... }
你可以做:

if(user is ITenant tenant)
{
     // access tenant.TenantId
}

您可以将
TenantId
添加到另一个接口,并在
TenantUser
中实现它。然后尝试转换到该界面:

public interface IUser
{
    int Id           { get; set; }
    string Username  { get; set; }
    string Email     { get; set; }
    string FirstName { get; set; }
    string LastName  { get; set; }
}
public class User : IUser
{
    public int Id           { get; set; }
    public string Username  { get; set; }
    public string Email     { get; set; }
    public string FirstName { get; set; }
    public string LastName  { get; set; }
}
public class TenantUser : IUser
{
    public int Id           { get; set; }
    public int TenantId     { get; set; }
    public string Username  { get; set; }
    public string Email     { get; set; }
    public string FirstName { get; set; }
    public string LastName  { get; set; }
}
鉴于:

interface ITenant
{
    int TenantId { get; set; }
}

public class TenantUser : IUser, ITenant
{ ... }
你可以做:

if(user is ITenant tenant)
{
     // access tenant.TenantId
}


浇铸到具体的物体上?否则你需要反射。嗯,有两个可能是具体的对象,所以我要试着在这两个对象上投射,看看它是哪一个?这就是界面变得丑陋的地方。它不是一个IUser,它是一个IUser和租户。虽然你可以,但这并不是一件可以妥协的事情。考虑一下你是否真的需要这样一个基本的PoCO对象的接口,抽象有一个非零成本。@ HANSPASANT你能看看我的评论下面的帖子吗?我知道自己的要求,是否可以避免这样做?将其投射到具体对象上?否则你需要反射。嗯,有两个可能是具体的对象,所以我要试着在这两个对象上投射,看看它是哪一个?这就是界面变得丑陋的地方。它不是一个IUser,它是一个IUser和租户。虽然你可以,但这并不是一件可以妥协的事情。考虑一下你是否真的需要这样一个基本的PoCO对象的接口,抽象有一个非零成本。@ HANSPASANT你能看看我的评论下面的帖子吗?在了解我的需求的情况下,我可以避免这样做吗?Selman你能展示一下我的TenantUser类是什么样子吗?看起来是一样的,只是在IUserI之后添加ITenant。我觉得我甚至处于这种情况是由于糟糕的编码实践,让我知道你的想法。我基本上在数据库中有一个Users表,在数据库中有一个TenantUsers表(除了TenantId之外,其他属性非常相似)。一个向api提交用户名和密码的登录页面。使用该用户名和密码,我首先需要查看他们是否可以作为管理员登录,然后重定向到管理员门户,如果不能,我需要查看他们是否可以作为租户登录,然后重定向到租户门户。我想我能避免这种情况的唯一方法是让一个Users表正确吗?@BlakeRivell您应该将类的所有公共成员隐藏在接口后面,以便处理允许多态性的接口。您不需要担心混凝土类型或浇铸方式。这就是为什么我建议在接口中添加
TenantId
,这样更好地设计IMHO。好吧,我在if语句中访问TenantId属性时遇到了问题。你能更新你答案中的最后一个代码块来告诉我怎么做吗?我需要先转换到TenantUser吗?Selman你能展示一下我的TenantUser类是什么样子吗?它看起来是一样的,只是在IUserI之后添加ITenant。我觉得我甚至在这种情况下都是因为糟糕的编码实践,让我知道你的想法。我基本上在数据库中有一个Users表,在数据库中有一个TenantUsers表(除了TenantId之外,其他属性非常相似)。一个向api提交用户名和密码的登录页面。使用该用户名和密码,我首先需要查看他们是否可以作为管理员登录,然后重定向到管理员门户,如果不能,我需要查看他们是否可以作为租户登录,然后重定向到租户门户。我想我能避免这种情况的唯一方法是让一个Users表正确吗?@BlakeRivell您应该将类的所有公共成员隐藏在接口后面,以便处理允许多态性的接口。您不需要担心混凝土类型或浇铸方式。这就是为什么我建议在接口中添加
TenantId
,这样更好地设计IMHO。好吧,我在if语句中访问TenantId属性时遇到了问题。你能更新你答案中的最后一个代码块来告诉我怎么做吗?我需要先投给租户吗?