Closed TokugawaTakeshi closed 1 year ago
Razorのビヘイビアクラスでジェネリックは対応していないようなので、
public partial class TextBox<TValue, TValidation> : ...
というような記述を行うとエラーがでるようです。
解決方法は、ジェネリックにせずに ・TValueとTValidationにはObjectを指定して、プロパティ経由でType情報を渡す。 ・インターフェイス型を渡す。 があります。
それと上記変更に伴って、Payloadクラスの部分も併せて変更が必要になってきます。 こちらは、 ・両方ともobject型で受けれるようにするか ・非ジェネリックのPayloadを用意するか ・インターフェイス型を渡してPayload内部で型解析するか 上記、対処方法が考えられます。
どちらにしても ・非ジェネリックで後から型情報を渡す ・インターフェイスに切り替える などの調整が必要となります。
@gummoni
なるほど・・・ 仕方あるまい、頑張ってオブジェクトやインターネットを使って実装します。
支援、感謝します。
@gummoni
TValue
をobject
にしました。
現在、そのままでthis.controlsPayload.familyName.GetExpectedToBeValidValue();
をthis.targetPerson.familyName
に割り当てますと、当然Cannot convert source type 'object' to target type 'string'
エラーが発生します。
public partial class PersonManager : Microsoft.AspNetCore.Components.ComponentBase
{
private void updatePersonIfInputtedDataIsValid()
{
if (this.targetPerson is null)
{
throw new Exception("「updatePersonIfInputtedDataIsValid」メソッドは呼び出されたが、「targetPerson」は「null」のまま。");
}
if (ValidatableControlsGroup.HasInvalidInputs(this.controlsPayload))
{
ValidatableControlsGroup.PointOutValidationErrors(this.controlsPayload);
}
this.targetPerson.familyName = this.controlsPayload.familyName.GetExpectedToBeValidValue();
}
}
現在、GetExpectedToBeValidValue
の実装は
public class Payload
{
protected object value;
protected readonly InputtedValueValidation validation;
protected InputtedValueValidationResult validationResult;
protected Func<IValidatableControl> componentInstanceAccessor;
public object Value
{
get => this.value;
set {
this.value = value;
this.validationResult = this.validation.Validate(this.value);
}
}
// ...
public object GetExpectedToBeValidValue()
{
if (this.IsInvalid)
{
throw new Exception("Contrary to expectations, the value is invalid.");
}
return this.Value;
}
}
です。型テックと、キャストをGetExpectedToBeValidValue
の中にやりたいと思います。
下記は妥当なコードになってはいませんが、その様に実装できますか?
public class Payload
{
// ...
public object GetExpectedToBeValidValue<TValue>()
{
if (this.IsInvalid)
{
throw new Exception("Contrary os expectations, the value is invalid.");
}
if (this.Value is TValue narrowedValidValue) {
return (TValue) narrowedValidValue;
}
throw new Exception("対象値の型は期待型と異なります。");
}
}
尚、値は任意な時、null
になっている事も有り得える事を考慮する必要があります。
この場合ならば
public object GetExpectedToBeValidValue<TValue>()
{
if (this.IsInvalid)
{
throw new Exception("Contrary os expectations, the value is invalid.");
}
if (this.Value is TValue narrowedValidValue) return narrowedValidValue;
throw new Exception("対象値の型は期待型と異なります。");
}
上記のようにメソッドにジェネリック型を用意して 関数内で型チェックを行う方法があります。
このような型チェックで実装していく手法をリフレクションプログラミングといって、型情報を用いてプログラムを書いていきます。
このプログラミングの参考URLを記載します。 https://qiita.com/gushwell/items/91436bd1871586f6e663
@gummoni
ありがとう、動かしました。
ただ一つ、public object GetExpectedToBeValidValue<TValue>()
をpublic TValue GetExpectedToBeValidValue<TValue>()
に変える必要があります。
@gummoni
を
に置き換えたら、クラスがpartialではなくなりました(詰まり、「TextBox.razor」との関連性が切れました)が、ジェネリックパラメーターを
ValidatableControl.Payload
に渡さなければいけません。どうすれば宜しいでしょうか?