.NET Core7 C#:无共同基类时修改不同对象的同属性
在.NET Core 7中修改无共同基类对象的Font属性(编译时校验)
方法一:静态抽象接口成员(原生编译时检查,.NET 7+专属)
这种方法无需修改现有类型,通过泛型约束让编译器直接校验类型是否具备Font属性。
- 定义带静态抽象成员的泛型接口,用于约束类型的
Font属性访问:
public interface IHasFont<T> { static abstract Font GetFont(T instance); static abstract void SetFont(T instance, Font value); }
- 为每个具备
Font属性的类型实现该接口(无需修改原类型代码,在自己的项目中实现即可):
// 为WinForms Button实现接口 public static class ButtonFontAccessor : IHasFont<Button> { public static Font GetFont(Button instance) => instance.Font; public static void SetFont(Button instance, Font value) => instance.Font = value; } // 为WinForms Label实现接口 public static class LabelFontAccessor : IHasFont<Label> { public static Font GetFont(Label instance) => instance.Font; public static void SetFont(Label instance, Font value) => instance.Font = value; }
- 编写泛型缩放方法,通过接口约束实现编译时校验:
private void RescaleFont<T>(T controlWithFont, double scale) where T : IHasFont<T> { var originalFont = IHasFont<T>.GetFont(controlWithFont); var newFont = new Font(originalFont.FontFamily, originalFont.Size * scale, originalFont.Style); IHasFont<T>.SetFont(controlWithFont, newFont); }
调用示例:
var button = new Button(); RescaleFont(button, 1.5); // 编译通过 var invalidObj = new object(); RescaleFont(invalidObj, 1.5); // 编译错误:object未实现IHasFont<object>
方法二:接口+包装类(兼容更早版本,编译时间接校验)
通过包装类将不同类型适配到统一接口,结合扩展方法实现编译时校验(无对应扩展方法则编译报错)。
- 定义统一接口:
public interface IHasFont { Font Font { get; set; } }
- 编写泛型包装类,用于适配不同类型的
Font属性:
public class FontWrapper<T> : IHasFont where T : class { private readonly T _instance; private readonly Func<T, Font> _fontGetter; private readonly Action<T, Font> _fontSetter; public FontWrapper(T instance, Func<T, Font> getter, Action<T, Font> setter) { _instance = instance; _fontGetter = getter; _fontSetter = setter; } public Font Font { get => _fontGetter(_instance); set => _fontSetter(_instance, value); } }
- 为每个具备
Font属性的类型编写扩展方法,生成包装实例:
public static class FontExtensions { public static IHasFont AsHasFont(this Button button) { return new FontWrapper<Button>(button, b => b.Font, (b, f) => b.Font = f); } public static IHasFont AsHasFont(this Label label) { return new FontWrapper<Label>(label, l => l.Font, (l, f) => l.Font = f); } // 其他具备Font属性的类型同理添加扩展 }
- 编写缩放方法,接收接口实例:
private void RescaleFont(IHasFont controlWithFont, double scale) { var originalFont = controlWithFont.Font; var newFont = new Font(originalFont.FontFamily, originalFont.Size * scale, originalFont.Style); controlWithFont.Font = newFont; }
调用示例:
var button = new Button(); RescaleFont(button.AsHasFont(), 1.5); // 编译通过 var invalidObj = new object(); RescaleFont(invalidObj.AsHasFont(), 1.5); // 编译错误:object无AsHasFont扩展方法
方法三:动态类型(不推荐,仅运行时校验)
如果无需编译时校验,可使用dynamic类型,但仅会在运行时抛出异常,不符合需求:
private void RescaleFont(dynamic controlWithFont, double scale) { var originalFont = controlWithFont.Font; var newFont = new Font(originalFont.FontFamily, originalFont.Size * scale, originalFont.Style); controlWithFont.Font = newFont; }
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

