继承的泛型

问题描述 投票:0回答:1

简单的模板问题。有人可以看看这个小提琴吗?我有一个

ClaimMessageController : MessageController
ClaimMessage : Message
MessageController.Send(TMessage)
,我希望能够将
ClaimMessage
传递给
ClaimMessageController
以获取用于 URL 替换的 ClaimId。

https://dotnetfiddle.net/FBh7yS

using System;
using System.Threading.Tasks;
using System.Reflection;
using System.IO;
using System.Linq;

public class MailWrapper {
    public async Task Send(string recipientEmailAddress, string recipientDisplayName, string subject, string htmlBody) {}
}

public class Message
{
    public string To { get; set; }
    public string ToName { get; set; }
}

public abstract class MessageController<TMessage> where TMessage : Message
{
    private readonly MailWrapper _mailWrapper;

    protected abstract string TemplatePath { get; }
    protected abstract string Subject { get; }

    protected MessageController(MailWrapper mailWrapper)
    {
        _mailWrapper = mailWrapper;
    }

    public async Task Send(TMessage message) =>
        await _mailWrapper.Send(message.To, message.ToName, RenderSubject(message), await RenderEmail(message));

    private string RenderSubject(Message message) =>
        message.GetType().GetProperties().Aggregate(Subject, (current, property) =>
            current.Replace("{{" + property.Name + "}}", property.GetValue(message)?.ToString(),
                StringComparison.InvariantCultureIgnoreCase));


    public virtual async Task<string> RenderEmail(Message message) =>
        message.GetType().GetProperties().Aggregate(
            await new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(TemplatePath)!)
                .ReadToEndAsync(),
            (current, property) =>
                current.Replace("{{" + property.Name + "}}", property.GetValue(message)?.ToString(),
                    StringComparison.InvariantCultureIgnoreCase));
}

public class ClaimMessage : Message
{
    public int ClaimId { get; set; }
}

public abstract class ClaimMessageController<TMessage> : MessageController<ClaimMessage>
{
    private readonly MailWrapper _mailWrapper;


    protected ClaimMessageController(MailWrapper mailWrapper) : base(mailWrapper)
    {
        _mailWrapper = mailWrapper;
    }

    public override Task<string> RenderEmail(TMessage message)
    {
        return base.RenderEmail(message);
    }

    public override async Task<string> RenderEmail(TMessage message) => (await base.RenderEmail((ClaimMessage)message)).Replace(
        "{{ClaimUrl}}", $"https://foo/claim/{message.ClaimId}",
        StringComparison.InvariantCultureIgnoreCase);
}
c# .net
1个回答
0
投票
public abstract class ClaimMessageController<TMessage>
: MessageController<ClaimMessage>

应该是

public abstract class ClaimMessageController<TMessage>
: MessageController<TMessage>
where TMessage : Message

您还存在相互冲突的

RenderEmail
覆盖。我认为摆脱第一个。

然后它还有一个不必要/不正确的转换为

ClaimMessage
RenderEmail
覆盖应如下所示:

public override async Task<string> RenderEmail(
    TMessage message
) => 
    (await base.RenderEmail(message))
    .Replace(
        "{{ClaimUrl}}",
        $"https://foo/claim/{((ClaimMessage)message).ClaimId}",
        StringComparison.InvariantCultureIgnoreCase
    );
© www.soinside.com 2019 - 2024. All rights reserved.