繁体   English   中英

泛型方法从超类获取参数类型

[英]Generic Method gets parameter type from superclass

我在C#中的类型化方法有问题。 我想调用对象的继承方法。 该方法调用以“ this”为参数的静态方法。 静态方法的参数是通用的。 现在,我希望此参数的通用类型是第一个对象的类型。 但是参数始终具有抽象类的类型。

这是示例:

abstract class AbstractClass
{
    bool update()
    {
        Connection.Update(this);
    }
}

class Entity : AbstractClass
{
}

class Connection
{
    public static void Update<T>(T obj)
    {
        someMethod<T>()
    }
}

如果我尝试这样做:

Entity foo = new Entity();
foo.update();

Connection.Update将在调试器中如下所示:

public static void Update<AbstractClass>(AbstractClass obj)
{
    someMethod<AbstractClass>()
}

但是我想要这个:

public static void Update<Entity>(Entity obj)
{
    someMethod<Entity>()
}

有没有可能

someMethod<typeof(obj)>()

还是要解决我的问题?

您可以将基类声明为通用类,下面是示例:

abstract class AbstractClass<T>
{
    bool update()
    {
        Connection.Update<T>(this as T);
    }
}

class Entity : AbstractClass<Entity>
{
}

class Connection
{
    public static void Update<T>(T obj)
    {
        someMethod<T>()
    }
}

如果你想速战速决再投thisdynamic ,这将延迟类型评估运行。 但是,请考虑使用访客模式。

public bool update()
{
    Connection.Update((dynamic)this);
    return true;
}

访客模式:

public interface IEntityVisitor
{
    void Visit(EntityBase entity);
    void Visit(Entity entity);
}

public interface IEntity
{
    void Accept(IEntityVisitor visitor);
}

public abstract class EntityBase : IEntity
{
    public virtual void Accept(IEntityVisitor visitor)
    {
        visitor.Visit(this);
    }
}

public class Entity : EntityBase
{
    public override void Accept(IEntityVisitor visitor)
    {
        visitor.Visit(this);
    }
}

编译器尝试推断T参数的类型,在基类中,编译器没有信息来推断Entity类型。 因此,当您要调用Update函数时,您应该提供子类型的信息。@ Alexandr答案是一个很好的选择,只是对T类型参数添加类型约束以限制它是AbstractClass的子对象的一种改进

abstract class AbstractClass<T>
where T: AbstractClass<T> //restrict T as a child of AbstractClass<T>
{
    bool update()
    {
        Connection.Update<T>(this as T);
    }
}

class Entity : AbstractClass<Entity>
{
}

class Connection
{
    public static void Update<T>(T obj)
    {
        someMethod<T>()
    }
}
var genericType = typeof(Connection<>);
var specificType = genericType.MakeGenericType(typeof(Entity));
var conn = Activator.CreateInstance(specificType);

someMethod<typeof(obj)>()不存在,因为它会破坏C#的类型安全性,因为编译器无法知道参数的运行时类型。 但是,您可以通过调用obj.GetType()获得真实类型的对象。 您可以使用此类型对象通过反射动态调用方法。

一种解决方案:

abstract class AbstractClass
{
    bool update<T>()
    {
        Connection.Update(T);
    }
}

然后,

Entity foo = new Entity();
foo.update<Entity>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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