注:この質問は新しい情報で更新されました。このテキストの下半分をご覧ください。 (元quesitonは、コンテキストのためにここに残されている。)基本クラスメソッドの属性を継承クラスに適用するにはどうすればよいですか?
それががオーバーライドされたメソッドで定義されていた場合、属性がまだ適用されているので、私は自分の属性を定義することができます任意の方法はありますか?
私は、メソッドに何らかの動作を挿入する属性を持っているが、そのメソッドが子クラスのいずれのケースでも呼び出されたときにその動作が適用されないので、さあ。
class BaseClass
{
[MyThing]
virtual void SomeMethod()
{
// Do something fancy because of the attribute.
}
}
class ChildClass
{
override void SomeMethod()
{
// Fancy stuff does happen here too...
base.SomeMethod();
}
void AnotherMethod()
{
// ...but not here. And I'd like it to =(
base.SomeMethod();
}
}
属性がそうのように定義されています。
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MyThingAttribute : Attribute
属性を持つメソッドを見つけるための現在のコードは以下の通りです:
var implementation = typeof(TheTypeWereCurrentlyInvestigating);
var allMethods = (from m in implementation.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
let attribs = (TransactionAttribute[]) m.GetCustomAttributes(typeof (TransactionAttribute), true)
where attribs.Length > 0
select Tuple.Create(m, attribs.Length > 0 ? attribs[0] : null)).ToList();
私はその部分を書いていない、と私は、私がそれのすべての部分の100%であるとは言えません...しかし、私は、今のところ、私が関与するすべてのコードを管理していると仮定することができます。 (これはオープンソースプロジェクトなので、少なくとも自分のバージョンを作成し、プロジェクトオーナーにパッチを提出することができます...)
私はいくつかの他のケースも持っています。どのような方法であっても、基本クラスのメソッドを呼び出しますが、私がこのクラスを解決すれば、他のクラスをどのように動作させるかについてのアイディアを得ることができます。そうでなければ、私は彼らと一緒に戻ってきます。
UPDATE:
OK、私はCastle.Transactionsプロジェクトに座っていませんどのような動作し、何を参照するには、いくつかの非常に簡単なテストを作成しました。それは、私の元々の仮定が何のために働いているのか、何がしていないのかはやや分かりませんでした。
私がやったこと:
私は属性で飾ら一つの方法を持ってテストクラスを作成し、これは動作が正常に注入したことを確認しAssert
メソッドを呼び出します(つまりトランザクションがあること)。その後、このテストクラスを継承するクラスをいくつか作成し、どのケースでもすべてが期待通りに動作することを確認しました。私が見つけた何
:
テストクラス上と子クラスのさまざまなメソッドから直接テストメソッドを呼び出すことで、私はしていませんどのような動作し、何について、次を発見しました:
Method called Access modifiers Does it work? ************* **************** ************* SomeMethod() on base class* N/A Yes OtherMethod() on child neither NO <-- headache! OtherMethod() on child hiding (new) No SomeMethod() on child hiding (new) No OtherMethod() on child overrides No OtherMethod() on child* overrides Yes SomeMethod() on child overrides Yes
*
と記されているものを除くすべてのケースにおいて、試験に適用された方法からbase.SomeMethod()
が呼び出されました。最初のケースでは、同じメソッドが呼び出されましたが、子クラスが含まれていないため、テストから直接呼び出しました。 2番目のケース(*
と表示されているもの)では、オーバーライドメソッドが呼び出されました。つまり、this.SomeMethod()
です。これは、最後のケースと実際は同じです。私は余分な修飾子を使用していないので、その方法では呼び出しは単にSomeMethod()
です。
は、私が欲しい:
は、それは私が本当に解決したい「頭痛」と記されたケースです。私が子クラスから呼び出しているにもかかわらず、基本クラスに動作を注入する方法。
私はこのパターンをリポジトリで使用しているので、基本クラスでは属性で修飾されたSave(T entity)
メソッドが定義されています。現在、トランザクションオーケストレーションを取得するためにこのメソッドをオーバーライドする必要があります。これにより、戻り値の型を変更できなくなります。基本クラスではvoid
ですが、私の実装では代わりにError<T>
にしたいと思います。これはオーバーライド時には不可能です。メソッドの名前を変更することで問題を解決できないため、私は迷っています。
なぜ「新しい」で「オーバーライド」されていないのですか?それは仮想であり、ベースを呼び出すので、「オーバーライド」はより単純に思えるでしょう。 –
@Marc:私はこの記事を書いた直後に、私が気づいたのは、私のケースのうちの1つを解決しましたが、両方を解決していませんでした。私の編集を見てください。オーバーライドするメソッドで発生する余分なもののため、私はいつも起こるとは限りません。残念ながら、AnotherMethodからオーバーライドされたメソッドを呼び出すことはできません。 –
@Tomas Lycken、 AnotherMethod()? – musefan