【问题标题】:Using the recursive function by making the type transformation in the generic method at run time通过在运行时在泛型方法中进行类型转换来使用递归函数
【发布时间】:2021-09-06 00:27:04
【问题描述】:

我有一个来自 AppLayerGroup 类的列表,在这个列表中我有另一个来自 AppLayer 类的列表。我想要做的是将发送到 TranslateList 方法的列表的每个属性翻译成我选择的语言。如果列表的每个属性的对应值存在于视图中,我更新它。如果属性是一个列表,我会尝试在递归函数的帮助下将新列表发送回 Translate 方法。但是类型'T'与第一次类型不同,我需要在运行时转换它但我不知道该怎么做。

    public class AppLayer : IEntity
    {
        public int Id { get; set; }
        public int AppLayerGroupId { get; set; }
        public string LayerName { get; set; }
    }

    public class AppLayerGroup : IEntity
    {
        public int Id { get; set; }
        public string GroupKey { get; set; }
        public virtual ICollection<AppLayer> AppLayer { get; set; }
    }
    public static IEnumerable<T> TranslateList<T>(this IEnumerable<T> data)
    {
        var _httpContextAccessor = (IHttpContextAccessor)ServiceTool.ServiceProvider.GetService(typeof(IHttpContextAccessor));
        var userId = _httpContextAccessor.HttpContext?.User.Claims.FirstOrDefault(x => x.Type.EndsWith("nameidentifier"))?.Value;
        var _cacheManager = (ICacheManager)ServiceTool.ServiceProvider.GetService(typeof(ICacheManager));

        short appLangId = Convert.ToInt16(_cacheManager.Get($"{CacheKeys.UserLang}={userId}"));

        Translate(data, appLangId);

        return data;
    }

    

    public static IEnumerable<T> Translate<T>(IEnumerable<T> data, short appLangId)
    {
        string classname = (data.FirstOrDefault() as Castle.DynamicProxy.IProxyTargetAccessor).DynProxyGetTarget().GetType().BaseType.Name;

        var _vAppLookupLanguageRepository = (IVAppLookupLanguageRepository)ServiceTool.ServiceProvider.GetService(typeof(IVAppLookupLanguageRepository));
        var langList = _vAppLookupLanguageRepository.GetList(a => a.EntityName == classname && a.AppLanguageId == appLangId);

        if (langList.IsAny() && data.IsAny())
        {
            foreach (var item in data )
            {
                foreach (PropertyInfo prop in item.GetType().GetProperties())
                {
                    if (prop.PropertyType.GetInterface("IEnumerable").Name == "IEnumerable")
                    {
                        var subList = (IEnumerable)prop.GetValue(item, null);

                        Translate((IEnumerable<T>)subList, 2); //I should submit the type of subList instead of 'T'
                    }
                    if (langList.Any(a => a.ColumnName == prop.Name))
                        prop.SetValue(item, langList.FirstOrDefault(a => a.UniqueValue == prop.GetValue(item).ToString()).LanguageValue, null);
                }
            }
        }

        return data;
    }

当我查询 AppLayerGroup 时,AppLayerGroup 列表将通过本地化每个列表元素内的属性返回。我希望它执行相同的操作并将其本地化到 AppLayerGroup 列表下的 AppLayer 列表中。

我做了一些研究,但找不到正确的结果。

【问题讨论】:

  • @Sinatr 我正在尝试翻译每个列表属性。我正在使用 T 能够发送到递归函数。你有更好的建议吗?
  • 我的错,我以某种方式将其理解为本地化。忽略我的评论。
  • 这看起来您的应用程序需要全球化和本地化。对吗?
  • @DanielDearlove 实际上试图准确地进行本地化。
  • @omerfarukaktas 如果您正在本地化,您是否已经遵循Globalization and Localization 的建议?另外,我仍在尝试弄清楚为什么您必须使用反射而不是为您的特定类创建 Translate() 方法?

标签: c# .net generics .net-core reflection


【解决方案1】:

如果您尝试翻译少数类中的字段,例如您的示例中的 AppLayerAppLayerGroup,则直接实现翻译并避免反射可能是更好的选择:

/// <summary>
/// Translates the string fields from the base language to a target language
/// </summary>
public static AppLayer Translate(AppLayer input, short appLangId)
{
    string classname = input.GetType().Name;
    var _vAppLookupLanguageRepository = (IVAppLookupLanguageRepository)ServiceTool.ServiceProvider.GetService(typeof(IVAppLookupLanguageRepository));
    var langList = _vAppLookupLanguageRepository.GetList(
        a => a.EntityName == classname && 
             a.AppLanguageId == appLangId &&
             a.ColumnName == "LayerName");

    string newLayerName = langList.FirstOrDefault(a => a.UniqueValue == input.LayerName).LanguageValue, null);

    return new AppLayer
    {
        Id = input.Id,
        AppLayerGroupId = input.AppLayerGroupId,
        LayerName = newLayerName
    };
}

我刚刚在键盘上敲了这个,所以它不会完全正确。如果您重构为一个通用的private static 翻译查找函数,在该函数中将语言存储库作为参数传递,那么您可以像处理AppLayer 一样处理AppLayerGroup 属性。您可以遍历 AppLayerGroup.AppLayer 集合。

【讨论】:

  • AppLayerGroup 只是一个小例子,项目中有很多这样的类我需要本地化,为它们编写不同的方法对我来说没有多大意义,并且这需要很多时间。
  • 这正是我所期望的。在已部署的应用程序中,我怀疑您是否可以应用 Source Generators 以便留下反射。我建议您至少设置一些需要转换的最复杂数据类型的测试用例。此外,可能值得添加一个类属性来标识可以翻译的类型,并且为不应该翻译的类型抛出异常。
猜你喜欢
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多