2017-09-15 69 views
0

将正在使用泛型的基类转换回其派生类型的正确方法是什么?将通用基础对象转换为派生类型

我有以下对象实现。

注意,“保存”方法调用“WriteSettings”的方法在这里(需要在BaseSettings对象)

public class Settings1 
{ 
    public string strData; 
} 

public class BaseSettings<T> 
{ 
    T settings; 
    public iSettingsDestination Destination; 

    public bool Save() 
    { 
     return Destination.WriteSettings(this); 
    } 
} 

public class Settings1Manager : BaseSettings<Settings1> 
{ 
    public bool DoSomething() 
    { 
     return true; 
    } 
} 

我已经创建了一个接口iSettingsDestination,将永远使用基类(BaseSettings)至传递对象。从iSettingsDestination派生的类可以选择要处理的对象类型。 我希望能够将此对象作为基本类型传递给方法,确定派生类型并反转投射。 (请参阅下文)尝试转回派生类型时收到编译错误。

public interface iSettingsDestination 
{ 
    bool WriteSettings<T>(BaseSettings<T> settings); 
} 

public class FileDestination : iSettingsDestination 
{ 
    bool WriteSettings1ManagerToFile(Settings1Manager settings) 
    { 
     // write to file 
     return true; 
    } 

    bool WriteSettings<T>(BaseSettings<T> settings) 
    { 
     if (typeof(Settings1Manager).IsAssignableFrom(settings.GetType())) 
     { 
      // generates error 
      // Cannot convert type 'BaseSettings<T>' to 'Settings1Manager' 
      return WriteSettings1ManagerToNetwork((Settings1Manager)settings); 
     } 

     // unhandled object type 
     return false; 
    } 

} 

我希望能够调用下面的代码。对于这里的示例,我只显示1种“目的地”和“设置”类型,但您可以想象这里可以使用许多不同的类型。

void main() 
    { 
     Settings1Manager settings1 = new Settings1Manager(); 
     settings1.Destination = new FileDestination(); 
     settings1.Save(); // saves to a file 
    } 

我能够做到这一点与其他基类,但似乎在这里使用泛型导致问题。

1)如何在调用WriteSettings1ManagerToNetwork((Settings1Manager)设置)中正确地将其转换回派生类型;

2)有没有人看到任何问题公然滥用泛型/接口/等逻辑在这里?

在此先感谢您的帮助。

回答

3

声明为BaseSettings<T>的引用指的是Settings1Manager的实际实例。这就是继承的工作原理。事实上,你正在做的是铸造一个基本类型的引用,它实际上是指你刚才确认的对象是派生类型的

settings as Settings1Manager会编译,因为如果转换失败,as将返回null。你和我都知道特定的演员阵容不会失败,但编剧只是遵循其规则。

if (typeof(Settings1Manager).IsAssignableFrom(settings.GetType())) 
{ 
    return WriteSettings1ManagerToNetwork(settings as Settings1Manager); 
} 

这工作太,因为你可以投什么object,你可以投object任何东西。但是你不希望人们在看起来像这样的代码上看到你的名字。

return WriteSettings1ManagerToFile((Settings1Manager)(object)settings); 
+1

太棒了!谢谢埃德! –

相关问题