私は何度も試しましたが、それでもカスタム属性の使い方を理解できません(すでにたくさんのリンクを調べました)。
コード付きのカスタム属性の非常に基本的な例を誰かに説明してもらえますか?
私は何度も試しましたが、それでもカスタム属性の使い方を理解できません(すでにたくさんのリンクを調べました)。
コード付きのカスタム属性の非常に基本的な例を誰かに説明してもらえますか?
回答:
カスタム属性を作成するコードはかなり単純ですが、属性が何であるかを理解することは非常に重要です。
属性は、プログラムにコンパイルされたメタデータです。属性自体は、クラス、プロパティ、またはモジュールに機能を追加するのではなく、データを追加するだけです。ただし、リフレクションを使用すると、機能を作成するためにこれらの属性を活用できます。
それでは、たとえば、MicrosoftのEnterprise LibraryのValidation Application Blockを見てみましょう。コード例を見ると、次のことがわかります。
/// <summary>
/// blah blah code.
/// </summary>
[DataMember]
[StringLengthValidator(8, RangeBoundaryType.Inclusive, 8, RangeBoundaryType.Inclusive, MessageTemplate = "\"{1}\" must always have \"{4}\" characters.")]
public string Code { get; set; }
上記のスニペットから、Validatorのルールに応じて、コードが変更されるたびに常に検証されると推測できます(例では、8文字以上8文字以下)。しかし、真実は属性は何もしないということです。前述のように、プロパティにメタデータを追加するだけです。
ただし、エンタープライズライブラリにはValidation.Validate
オブジェクトを調べるメソッドがあり、プロパティごとに、コンテンツが属性によって通知されたルールに違反しているかどうかをチェックします。
したがって、属性について考える必要があります-後で他のメソッド/クラスなどで使用される可能性があるコードにデータを追加する方法です。
public class MyCustomAttribute: Attribute
{
public string SomeProperty { get; set; }
}
次に、この属性で何でも(クラス、メソッド、プロパティなど)装飾できます。
[MyCustomAttribute(SomeProperty = "foo bar")]
public class Foo
{
}
最後に、リフレクションを使用してそれをフェッチします。
var customAttributes = (MyCustomAttribute[])typeof(Foo).GetCustomAttributes(typeof(MyCustomAttribute), true);
if (customAttributes.Length > 0)
{
var myAttribute = customAttributes[0];
string value = myAttribute.SomeProperty;
// TODO: Do something with the value
}
AttributeUsage属性を使用して、このカスタム属性を適用できるターゲットタイプを制限できます。
/// <summary>
/// This attribute can only be applied to classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute
属性について知っておくべき重要なこと:
var value = typeof(Foo).GetCustomAttributes<MyCustomAttribute>().First().SomeProperty;
Darin Dimitrovの素晴らしいレスポンスを利用/コピーします。これは、クラスではなくプロパティのカスタム属性にアクセスする方法です。
[クラスのFoo
] 装飾されたプロパティ:
[MyCustomAttribute(SomeProperty = "This is a custom property")]
public string MyProperty { get; set; }
それを取得する:
PropertyInfo propertyInfo = typeof(Foo).GetProperty(propertyToCheck);
object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
if (attribute.Length > 0)
{
MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
string propertyValue = myAttribute.SomeProperty;
}
これをループでスローし、リフレクションを使用して、classの各プロパティのこのカスタム属性にアクセスすることもできますFoo
。
foreach (PropertyInfo propertyInfo in Foo.GetType().GetProperties())
{
string propertyName = propertyInfo.Name;
object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
// Just in case you have a property without this annotation
if (attribute.Length > 0)
{
MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
string propertyValue = myAttribute.SomeProperty;
// TODO: whatever you need with this propertyValue
}
}
ダーリン、ありがとう!
object[] attribute = propertyInfo.GetCustomAttributes(typeof(???), true);
私はそれらすべてを反復処理して、m1()
不明な各属性のメソッドを呼び出したいだけです
短い答えは、c#で属性を作成するためのもので、Attributeクラスから継承する必要があるだけです。これは:)
しかし、ここでは属性について詳しく説明します。
基本的に属性は、アセンブリ、クラス、メソッド、プロパティ、フィールドなどにロジックを適用するために使用できるクラスです。
.Netでは、Microsoftは([必須]、[StringLength(100)]、[Range(0、999.99)])などの廃止または検証属性などのいくつかの定義済み属性を提供しています。また、asp.netにActionFiltersのような属性がありますこれは、必要なロジックをコードに適用するのに非常に役立ちます(学習に情熱を傾けている場合は、アクションフィルターに関するこの記事を参照してください)。
もう1つのポイントは、AttibuteUsageを介して属性に一種の構成を適用できることです。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
AttributeUsageで属性クラスを装飾するとき、この属性をどこで使用するかをc#コンパイラーに伝えることができます。これは、クラス、プロパティのアセンブリ、または...で使用し、属性の使用を許可されます定義されたターゲット(クラス、アセンブリ、プロパティなど)で数回ですか?
属性に関するこの定義の後で、例を示します。大学で新しいレッスンを定義し、大学の管理者とマスターだけが新しいレッスンを定義できるようにしたいとします。
namespace ConsoleApp1
{
/// <summary>
/// All Roles in our scenario
/// </summary>
public enum UniversityRoles
{
Admin,
Master,
Employee,
Student
}
/// <summary>
/// This attribute will check the Max Length of Properties/fields
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
public class ValidRoleForAccess : Attribute
{
public ValidRoleForAccess(UniversityRoles role)
{
Role = role;
}
public UniversityRoles Role { get; private set; }
}
/// <summary>
/// we suppose that just admins and masters can define new Lesson
/// </summary>
[ValidRoleForAccess(UniversityRoles.Admin)]
[ValidRoleForAccess(UniversityRoles.Master)]
public class Lesson
{
public Lesson(int id, string name, DateTime startTime, User owner)
{
var lessType = typeof(Lesson);
var validRolesForAccesses = lessType.GetCustomAttributes<ValidRoleForAccess>();
if (validRolesForAccesses.All(x => x.Role.ToString() != owner.GetType().Name))
{
throw new Exception("You are not Allowed to define a new lesson");
}
Id = id;
Name = name;
StartTime = startTime;
Owner = owner;
}
public int Id { get; private set; }
public string Name { get; private set; }
public DateTime StartTime { get; private set; }
/// <summary>
/// Owner is some one who define the lesson in university website
/// </summary>
public User Owner { get; private set; }
}
public abstract class User
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Master : User
{
public DateTime HireDate { get; set; }
public Decimal Salary { get; set; }
public string Department { get; set; }
}
public class Student : User
{
public float GPA { get; set; }
}
class Program
{
static void Main(string[] args)
{
#region exampl1
var master = new Master()
{
Name = "Hamid Hasani",
Id = 1,
DateOfBirth = new DateTime(1994, 8, 15),
Department = "Computer Engineering",
HireDate = new DateTime(2018, 1, 1),
Salary = 10000
};
var math = new Lesson(1, "Math", DateTime.Today, master);
#endregion
#region exampl2
var student = new Student()
{
Name = "Hamid Hasani",
Id = 1,
DateOfBirth = new DateTime(1994, 8, 15),
GPA = 16
};
var literature = new Lesson(2, "literature", DateTime.Now.AddDays(7), student);
#endregion
ReadLine();
}
}
}
プログラミングの現実の世界では、属性を使用するためにこのアプローチを使用しない可能性があります。属性を使用することの教育的理由のため、私はこれを述べました