如何在单个方法中兼容传入Product或Category类型对象?
解决方案
针对你需要让日志方法兼容Product和Category两种类型的场景,因为二者属性结构完全一致,可以通过以下几种方式实现:
方法一:定义公共接口(推荐方案)
通过抽象公共属性结构来实现多态复用,这是类型安全且性能最优的方式:
- 先定义一个包含公共属性的接口:
public interface IHasContentImages { // 这里的类型要和你的CategoryImages实际类型匹配 ImageCollection CategoryImages { get; } } // 补充对应的依赖类型定义(根据你的实际代码调整) public class ImageCollection { public List<ImageItem> Items { get; set; } } public class ImageItem { public ContentLink ContentLink { get; set; } } public class ContentLink { public Guid ID { get; set; } public string ProviderName { get; set; } public bool GetPublishedOrLatest { get; set; } }
- 让Product和Category类实现这个接口:
public class Product : IHasContentImages { public ImageCollection CategoryImages { get; set; } // 其他Product专属属性 } public class Category : IHasContentImages { public ImageCollection CategoryImages { get; set; } // 其他Category专属属性 }
- 修改日志方法,接收接口类型参数:
public void LogContentLinkInformation(IHasContentImages itemWithImages) { // 提前判空避免空引用 if (itemWithImages?.CategoryImages?.Items == null) return; foreach (var imageItem in itemWithImages.CategoryImages.Items) { var contentLink = imageItem.ContentLink; if (contentLink == null) continue; _logger.LogDebug(nameof(ProcessFiles), $"Content Link Id: {contentLink.ID.ToString()}"); _logger.LogDebug(nameof(ProcessFiles), $"Provider Name: {contentLink.ProviderName}"); _logger.LogDebug(nameof(ProcessFiles), $"GetPublishedOrLatest: {contentLink.GetPublishedOrLatest.ToString()}"); } }
调用时直接传入Product或Category对象即可:
var product = new Product(); LogContentLinkInformation(product); var category = new Category(); LogContentLinkInformation(category);
方法二:泛型+反射(适用于无法修改原有类的场景)
如果你不能修改Product和Category的源代码,无法让它们实现接口,可以用反射来读取公共属性:
public void LogContentLinkInformation<T>(T item) { if (item == null) return; // 反射获取CategoryImages属性 var categoryImagesProp = typeof(T).GetProperty(nameof(Category.CategoryImages)); if (categoryImagesProp == null) return; var categoryImages = categoryImagesProp.GetValue(item); if (categoryImages == null) return; // 获取Items集合 var itemsProp = categoryImages.GetType().GetProperty(nameof(ImageCollection.Items)); if (itemsProp == null) return; var items = itemsProp.GetValue(categoryImages) as IEnumerable; if (items == null) return; foreach (var imageItem in items) { if (imageItem == null) continue; // 获取ContentLink属性 var contentLinkProp = imageItem.GetType().GetProperty(nameof(ImageItem.ContentLink)); if (contentLinkProp == null) continue; var contentLink = contentLinkProp.GetValue(imageItem); if (contentLink == null) continue; // 读取并日志ContentLink的各个属性 var idProp = contentLink.GetType().GetProperty(nameof(ContentLink.ID)); var providerNameProp = contentLink.GetType().GetProperty(nameof(ContentLink.ProviderName)); var getPublishedProp = contentLink.GetType().GetProperty(nameof(ContentLink.GetPublishedOrLatest)); if (idProp != null) _logger.LogDebug(nameof(ProcessFiles), $"Content Link Id: {idProp.GetValue(contentLink)?.ToString()}"); if (providerNameProp != null) _logger.LogDebug(nameof(ProcessFiles), $"Provider Name: {providerNameProp.GetValue(contentLink)}"); if (getPublishedProp != null) _logger.LogDebug(nameof(ProcessFiles), $"GetPublishedOrLatest: {getPublishedProp.GetValue(contentLink)?.ToString()}"); } }
注意:反射会有一定性能损耗,高频调用场景不建议用。
方法三:动态类型(简单但无编译检查)
这种方式最简洁,但失去了编译时类型校验,一旦属性名变更会导致运行时错误:
public void LogContentLinkInformation(dynamic item) { if (item?.CategoryImages?.Items == null) return; foreach (var imageItem in item.CategoryImages.Items) { var contentLink = imageItem.ContentLink; if (contentLink == null) continue; _logger.LogDebug(nameof(ProcessFiles), $"Content Link Id: {contentLink.ID.ToString()}"); _logger.LogDebug(nameof(ProcessFiles), $"Provider Name: {contentLink.ProviderName}"); _logger.LogDebug(nameof(ProcessFiles), $"GetPublishedOrLatest: {contentLink.GetPublishedOrLatest.ToString()}"); } }
调用时直接传两种类型对象即可,但开发阶段无法提前发现属性不匹配的问题。
内容的提问来源于stack exchange,提问作者S92
相关产品推荐
相关产品推荐

