简体   繁体   English

在派生的 class 中永久向下转换泛型

[英]Permanently downcast a generic in a derived class

Ok so the scenario is I have several services that share similar behaviors and all contain settings that are shared across them.好的,场景是我有几个共享相似行为的服务,并且都包含在它们之间共享的设置。

These services have their own extended service specific settings which I am unable to access in the derived service class. Below is essentially an example of what I am trying to do.这些服务有自己的扩展服务特定设置,我无法在派生服务 class 中访问这些设置。下面基本上是我正在尝试做的事情的示例。

public abstract class BaseSettings<T> where T : ISettings
{
  public string BaseSetting { get; } = "Hello from BaseSettings";
  // other settings, etc.

  public BaseSettings<T>() {}
}

public abstract class BaseService<T> where T : ISettings
{
  public BaseSettings<T> Settings { get; }

  public BaseService(BaseSettings<T> settings)
  {
    Settings = settings;
    Console.WriteLine(Settings.BaseSetting);
  }
}

public class ServiceASettings : BaseSettings<ServiceASettings>, ISettings
{
  public string SettingA { get; } = "Hello from SettingsA";

  public ServiceASettings() {}
}

public class ServiceA : BaseService<ServiceASettings>, IService
{
  public ServiceA(ServiceASettings settings) : base(settings) 
  {
   Console.WriteLine(Settings.SettingA); // cant see this property
   Console.WriteLine((Settings as SettingsA).SettingA); // prints fine
  }
}

// ServiceB, ServiceBSettings; ServiceC, ServiceCSettings; etc...

public class Program
{
  public static void Main(string[] args)
  {
    SettingsA settings = new SettingsA();
    ServiceA service = new ServiceA(settings);
    // does not compile because says there is no definition for 
    // Settings.SettingA within ServiceA
  }
}

I cannot figure out how to dynamically downcast(?) the Settings in the derived Service class to access them or essentially make them the appropriate concrete class.我无法弄清楚如何动态向下转换(?)派生服务 class 中的设置以访问它们或本质上使它们成为适当的具体 class。

Is there a way to permanently set Settings as the appropriate derived class or do I have to call the specific properties using casting on everything?有没有办法将设置永久设置为适当的派生 class,或者我是否必须在所有内容上使用强制转换来调用特定属性?

ie avoid (Settings as SettingsA).PropertyA; (Settings as SettingsB).PropertyB即避免(Settings as SettingsA).PropertyA; (Settings as SettingsB).PropertyB (Settings as SettingsA).PropertyA; (Settings as SettingsB).PropertyB and so on? (Settings as SettingsA).PropertyA; (Settings as SettingsB).PropertyB等等?

Would appreciate if someone can explain how to accomplish this or if there is an easier way since may be over complicating this.如果有人可以解释如何完成此操作,或者是否有更简单的方法,我们将不胜感激,因为这可能会使它过于复杂。

Any help is appreciated.任何帮助表示赞赏。

Solution解决方案

changes made to get it to work为使其正常工作所做的更改

public abstract class BaseSettings
{
  public string BaseSetting { get; } = "Hello from BaseSettings";
  // other settings, etc.

  public BaseSettings() {}
}

public abstract class BaseService<T> where T : ISettings
{
  public T Settings { get; }

  public BaseService(T settings)
  {
    Settings = settings;
    Console.WriteLine(Settings.BaseSetting);
  }
}

public class ServiceASettings : BaseSettings, ISettings
{
  public string SettingA { get; } = "Hello from SettingsA";

  public ServiceASettings() {}
}

Thanks to Ann for the suggestions.感谢安的建议。

This might be the problem:这可能是问题所在:

You have BaseService.Settings defined this way:您以这种方式定义了BaseService.Settings

public abstract class BaseService<T> where T : ISettings
{
  public BaseSettings<T> Settings { get; }
}

It should probably be like this instead:它可能应该是这样的:

public abstract class BaseService<T> where T : ISettings
{
  public T Settings { get; }
}

The explanation: in your ServiceA , in the original implementation, your Settings property is going to be a BaseSettings<ServiceASettings> , not a ServiceASettings .解释:在您的ServiceA中,在原始实现中,您的Settings属性将是BaseSettings<ServiceASettings> ,而不是ServiceASettings And BaseSettings<T> never exposes a property of type T , so there's no way from within ServiceA to access a property of type ServiceASettings .并且BaseSettings<T>从不公开T类型的属性,因此无法从ServiceA内部访问ServiceASettings类型的属性。

I don't think BaseSettings necessarily needs to take a generic type at all (based on what you've shown us), or if it does, that it needs to take another derivation of ISettings as its generic type, unless you're going to expose an instance of T from it.我认为BaseSettings不需要采用通用类型(根据您向我们展示的内容),或者如果需要,它需要采用ISettings的另一种派生作为其通用类型,除非您要从中公开T的实例。

There are a couple of other ways to approach the problem, as well.还有一些其他方法可以解决这个问题。

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

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