Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Reflection - Complicate Example in C#
Mình khá là lười, nên mình sẽ không đưa định nghĩa hay usage của reflection vào đây. Vì dù sao mình cũng sẽ chỉ copy thôi . Vậy nên chúng ta đi thằng vào ví dụ luôn nhé.
Mình tạo ra một class Person và mình muốn user đưa tên và tuổi của Person vào. Mình muốn đặt ra một số từ bị cấm trong attribute Name (Hoặc trong bất cứ attribute nào là string). Đầu tiên mình tạo class Person.
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Sau đó mình tạo class ForbiddenWordAttribute Class sử dụng Attribute.
[AttributeUsage(AttributeTargets.Property,AllowMultiple =false)]
class ForbiddenWordAttribute: Attribute
{
public string word { get; private set; }
public ForbiddenWordAttribute(string word)
{
this.word = word;
}
}
Syntax để định nghĩa một Attribute là:
[AttributeUsage(
validon — target, in here is property
AllowMultiple=allowmultiple — optional
Inherited=inherited — optional
)]
Sau đó mình tạo class ForbiddenWordValidation để tạo logic cho ForbidenWordAttribute.
class ForbiddenWordValidation : IValidation
{
public bool Validate(object instance, PropertyInfo property)
{
ForbiddenWordAttribute word = property.GetCustomAttribute<ForbiddenWordAttribute>();
if(property.PropertyType == typeof(string))
{
string value = (string)property.GetValue(instance);
return !value.Contains(word.word);
}
else
{
throw new InvalidOperationException();
}
}
}
Ở đây mình tạo một explicit interface Ivalidation sẽ chứa bool Validate để xác định logic. Mình tao nó vì mình không biết tương lai liệu có Attribute nào có cùng target không, nếu có mình có thể để nó sử dụng interface này để giảm bớt việc viết lại bool Validate.
Logic ở đây khá đơn giản, Mình check xem property có phải string không, nếu phải thì mình check xem nó có chưa forbidden word không. Nếu có thì trả về False, không thì về True. Nếu User dùng Attribute này với property không phải string thì throw Exception.
Vì mình không chắc mình sẽ chỉ dùng 1 attributes trong tương lai nên mình đẩy hết về 1 class để dễ xử lí. Cái đó gọi là Factory Pattern.
class ValidatorFactory
{
public IValidation GetValidation(Attribute attribute)
{
if(attribute is ForbiddenWordAttribute)
{
return new ForbiddenWordValidation();
}
return null;
}
}
Cuối cùng mình dùng class Validator để kiểm tra mọi thứ và wrap mọi thứ lại.
class Validator
{
public bool Validate(object instance)
{
ValidatorFactory factory = new ValidatorFactory();
PropertyInfo[] properties = instance.GetType().GetProperties();
foreach(PropertyInfo property in properties)
{
var attributes = property.GetCustomAttributes();
foreach(Attribute attr in attributes)
{
IValidation validation = factory.GetValidation(attr);
if(attr != null && !validation.Validate(instance,property))
{
return false;
}
}
}
return true;
}
}
Giờ mình quay lại class Person để set Forbidden word là "Hoang"
class Person
{
[ForbiddenWord(“Hoang”)]
public string Name { get; set; }
public int Age { get; set; }
}
Giờ chúng ta test trong Main Program:
class Program
{
static void Main(string[] args)
{
Person goodPerson = new Person { Name = “Rice”, Age = 22 };
Person badPerson = new Person { Name = “Hoang”, Age = 22 };
Validator validator = new Validator();
Console.WriteLine($”FIRST: {validator.Validate(goodPerson)}”);
Console.WriteLine($”SECOND: {validator.Validate(badPerson)}”);
Console.ReadLine();
}
}
Vậy là xong một cái ví dụ phức tạp rồi. :D
Full source code: https://github.com/PhiHuyHoang/Programming3/tree/master/Reflection/Reflection





