编辑
2025-02-09
C# 应用
00
请注意,本文编写于 86 天前,最后修改于 86 天前,其中某些信息可能已经过时。

目录

1. 使用Lambda表达式获取属性名称
2. 对象映射
3. 通用仓储模式
4. 动态属性访问器

高级C#开发人员经常利用反射和泛型来简化代码,提高效率。这些技巧可以帮助我们避免编写大量重复代码,同时提高代码的可维护性。本文将介绍几个使用反射和泛型的高级技巧,并提供详细的示例。

1. 使用Lambda表达式获取属性名称

在C#中,我们经常需要引用对象的属性名称。直接使用字符串硬编码属性名称可能会导致在重构时出现问题。使用Lambda表达式可以安全地获取属性名称,即使在重命名属性时也能保持代码的正确性。

C#
// 使用示例 class Person { public string Name { get; set; } } internal class Program { public static string PropertyName<TEntity, TProp>(Expression<Func<TEntity, TProp>> expression) { MemberExpression member = expression.Body as MemberExpression; return member.Member.Name; } static void Main(string[] args) { var nameProp = PropertyName((Person p) => p.Name); Console.WriteLine(nameProp); // 输出: "Name" } }

image.png

2. 对象映射

在业务应用中,我们经常需要在不同的对象之间映射属性。使用反射和泛型,我们可以创建一个通用的映射器,大大减少重复代码。

C#
// 使用示例 class SourceObject { public int Id { get; set; } public string Name { get; set; } } class TargetObject { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } } public class Mapper<TSource, TTarget> where TSource : class where TTarget : class { public TTarget Map(TSource source) { TTarget target = Activator.CreateInstance<TTarget>(); var sourceProperties = typeof(TSource).GetProperties(); var targetProperties = typeof(TTarget).GetProperties(); foreach (var sourceProp in sourceProperties) { var targetProp = targetProperties.FirstOrDefault(p => p.Name == sourceProp.Name && p.PropertyType == sourceProp.PropertyType); if (targetProp != null && targetProp.CanWrite) { targetProp.SetValue(target, sourceProp.GetValue(source)); } } return target; } } internal class Program { static void Main(string[] args) { var mapper = new Mapper<SourceObject, TargetObject>(); var source = new SourceObject { Id = 1, Name = "Test" }; var target = mapper.Map(source); Console.WriteLine($"Id: {target.Id}, Name: {target.Name}"); } }

image.png

3. 通用仓储模式

使用泛型和反射,我们可以实现一个通用的仓储模式,适用于不同的实体类型。

C#
public interface IRepository<T> where T : class { T GetById(int id); IEnumerable<T> GetAll(); void Add(T entity); void Update(T entity); void Delete(T entity); } public class GenericRepository<T> : IRepository<T> where T : class { private readonly DbContext _context; private readonly DbSet<T> _dbSet; public GenericRepository(DbContext context) { _context = context; _dbSet = context.Set<T>(); } public T GetById(int id) { return _dbSet.Find(id); } public IEnumerable<T> GetAll() { return _dbSet.ToList(); } public void Add(T entity) { _dbSet.Add(entity); } public void Update(T entity) { _dbSet.Attach(entity); _context.Entry(entity).State = EntityState.Modified; } public void Delete(T entity) { if (_context.Entry(entity).State == EntityState.Detached) { _dbSet.Attach(entity); } _dbSet.Remove(entity); } } // 使用示例 class User { public int Id { get; set; } public string Name { get; set; } } var userRepository = new GenericRepository<User>(dbContext); var user = userRepository.GetById(1); userRepository.Update(user);

4. 动态属性访问器

使用反射,我们可以创建一个动态的属性访问器,允许我们在运行时访问和修改对象的属性。

C#
public class DynamicPropertyAccessor<T> where T : class { private readonly Dictionary<string, PropertyInfo> _properties; public DynamicPropertyAccessor() { _properties = typeof(T).GetProperties().ToDictionary(p => p.Name); } public object GetPropertyValue(T obj, string propertyName) { if (_properties.TryGetValue(propertyName, out PropertyInfo propInfo)) { return propInfo.GetValue(obj); } throw new ArgumentException($"Property {propertyName} not found."); } public void SetPropertyValue(T obj, string propertyName, object value) { if (_properties.TryGetValue(propertyName, out PropertyInfo propInfo)) { propInfo.SetValue(obj, value); } else { throw new ArgumentException($"Property {propertyName} not found."); } } } // 使用示例 class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } internal class Program { static void Main(string[] args) { var accessor = new DynamicPropertyAccessor<Product>(); var product = new Product { Id = 1, Name = "Laptop", Price = 999.99m }; Console.WriteLine(accessor.GetPropertyValue(product, "Name")); accessor.SetPropertyValue(product, "Price", 1099.99m); Console.WriteLine(product.Price); } }

image.png

这些高级技巧展示了如何使用反射和泛型来创建更加灵活和可重用的代码。通过掌握这些技巧,我们可以编写出更加简洁、高效的C#程序,同时提高代码的可维护性和可扩展性。

本文作者:rick

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!