如何创建动态方法?

huangapple go评论85阅读模式
英文:

How to create Dynamic Method?

问题

我有一些方法,每个方法都检查相同的一组条件,如果条件都不满足,则返回null值,否则返回不同类的对象。
有没有办法不必为每个函数都写这些条件,减少代码量?

public A methode1()
{
    if ///something
        return A("xxx")
    else if ///something
        return A("yyy")
    else if ///something
        return A("zzzz")
    else 
        return Error() // 或者返回null
}

public B methode2()
{
    if ///something
        return B("mmmm")
    else if ///something
        return B("nnn")
    else if ///something
        return B("bbbb")
    else
        return Error() // 或者返回null
}

public C methode3()
{
    if ///something
        return C("oooo")
    else if ///something
        return C("ggg")
    else if ///something
        return C("llll")
    else
        return Error() // 或者返回null
}
英文:

I have a number of methods, each of which checks the same set of conditions and returns a null value if none of the conditions are met, otherwise returns an object of different classes.
Is there a way to not have to write all of these terms for each function and use less code?

    public A methode1()
    {
        if ///something
            return A("xxx")
        else if ///something
            return A("yyy")
        else if ///something
            return A("zzzz")
        else 
            return Error() // or return null
    }
    public B methode2()
    {
        if ///something
            return B("mmmm")
        else if ///something
            return B("nnn")
        else if ///something
            return B("bbbb")
        else
            return Error() // or return null
    }

    public C methode3()
    {
        if ///something
            return C("oooo")
        else if ///something
            return C("ggg")
        else if ///something
            return C("llll")
        else
            return Error() // or return null
    }

答案1

得分: 1

标准方法是,您可以使用带有接口/抽象类的工厂类。

public interface IOutput {
}
public class Output1 : IOutput{
}
public class Output2 : IOutput{
}
public class MyFactory
{
    public IOutput Get()// 添加任何参数列表
    {
       if(条件) // 如果必要,可以在条件中使用参数
           return new Output1();
       else
           return new Output2();
    }
}
英文:

Standard approch is , you can use a factory class with interface/abstract class

public interface IOutput {
}
public class Output1 : IOutput{
}
public class Output2 : IOutput{
}
public class MyFactory
{
    public IOutput Get()// add args list of any
    {
       if(condition) // you can use args in condition if necessary
           return new Output1();
       else
           return new Output2();
    }
}

答案2

得分: 1

你可以将模板方法模式泛型结合使用:

public abstract class AbstractTemplate<T>
{
    public T Method()
    {
        if ///something
            return Do1();
        else if ///something
            return Do2();
        else if ///something
            return Do3();
        else 
            return Error(); // 或者返回 null
    }
    protected abstract T Do1();
    protected abstract T Do2();
    protected abstract T Do3();
}

public class ConcreteATemplate : AbstractTemplate<A>
{
    protected override A Do1() => A("xxx");
    protected override A Do2() => A("yyy");
    protected override A Do3() => A("zzzz");
}

然后在你的方法中使用它:

```csharp
public A Method1() => new ConcreteATemplate().Method(); // 也可以在你的情况下“缓存”实例在静态 readonly 字段中。

[1]: https://en.wikipedia.org/wiki/Template_method_pattern
[2]: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
英文:

You can combine template method pattern with generics:

public abstract class AbstractTemplate&lt;T&gt;
{
    public T methode()
    {
        if ///something
            return Do1();
        else if ///something
            return Do2();
        else if ///something
            return Do3();
        else 
            return Error() // or return null
    }
    protected abstract T Do1();
    protected abstract T Do2();
    protected abstract T Do3();
}

public class ConcreteATemplate : AbstractTemplate&lt;A&gt;
{
    protected override T Do1() =&gt; A(&quot;xxx&quot;);
    protected override T Do2() =&gt; A(&quot;yyy&quot;);
    protected override T Do3() =&gt; A(&quot;zzzz&quot;);
}

And use it inside your methods:

public A methode1() =&gt; new ConcreteATemplate().methode(); // also can &quot;cache&quot; instance in your case in static readonly field.

答案3

得分: 0

你可以使用具有通用类型参数和一组初始值的方法。

private T GetIfOkay<T>(string a, string b, string c)
    where T : new()
{
    if (something)
        return new T(a);
    else if (something else)
        return new T(b);
    else if (yet something else)
        return new T(c);
    else
        return null;
}

public A methode1()
{
    return GetIfOkay<A>("xxx", "yyy", "zzzz");
}

public B methode2()
{
    return GetIfOkay<B>("mmmm", "nnn", "bbbb");
}

// etc.

如果需要更动态的行为,可以参考 @donggas90 的解决方案。

参见:

英文:

You could use a method with a generic type parameter and a set of initial values.

private T GetIfOkay&lt;T&gt;(string a, string b, string c)
    where T : new()
{
    if (something)
        return new T(a);
    else if (something else)
        return new T(b);
    else if (yet something else)
        return new T(c);
    else
        return null;
}

public A methode1()
{
    return GetIfOkay&lt;A&gt;(&quot;xxx&quot;, &quot;yyy&quot;, &quot;zzzz&quot;);
}

public B methode2()
{
    return GetIfOkay&lt;B&gt;(&quot;mmmm&quot;, &quot;nnn&quot;, &quot;bbbb&quot;);
}

// etc.

If you need a more dynamic behaviour, @donggas90's solution.

See:

答案4

得分: 0

你可以使用通用方法和仓储模式。以下是一个使用C#的通用方法示例,我认为它可能会给你一些想法:

public static async Task<List<ObjectType>> GetDataList<ObjectType>(UserAuthorization token) where ObjectType : BaseModel
{
    List<ObjectType> data = new List<ObjectType>();
    try
    {
        if (token.UserTypes.Count > 0)
        {
            Type genericClass = typeof(Repository<>);
            Type constructedClass = genericClass.MakeGenericType(typeof(ObjectType));
            MERPDbContext mERPContext = new MERPDbContext();
            var created = (Repository<ObjectType>)Activator.CreateInstance(constructedClass, mERPContext);
            if (token.UserTypes[0].Id == (byte)UserTypes.SuperAdmin)
            {
                var sub = await created.GetAsync();
                data = sub.ToList();
            }
            else if (token.UserTypes[0].Id == (byte)UserTypes.InstituteAdmin)
            {
                data = await created.FilterListAsync(x => x.InstituteId == token.InstituteID);
            }
            else
            {
                data = await created.FilterListAsync(x =>
                    x.InstituteId == token.InstituteID && x.CampusId == token.CampusID);
            }
        }
    }
    catch (Exception e)
    {

    }
    return data;
}

请注意,这是提供给你的通用方法示例,具体的实现可能需要根据你的应用程序需求进行调整。

英文:

You can use generic method and repository pattern. Here is a generic method example with C#. I think it may give you some idea..

public static async Task&lt;List&lt;ObjectType&gt;&gt; GetDataList&lt;ObjectType&gt;(UserAuthorization token) where ObjectType : BaseModel
        {
            List&lt;ObjectType&gt; data = new List&lt;ObjectType&gt;();
            try
            {
                if(token.UserTypes.Count &gt; 0)
                {
                    Type genericClass = typeof(Repository&lt;&gt;);
                    Type constructedClass = genericClass.MakeGenericType(typeof(ObjectType));
                    MERPDbContext mERPContext = new MERPDbContext();
                    var created = (Repository&lt;ObjectType&gt;)Activator.CreateInstance(constructedClass, mERPContext);
                    if (token.UserTypes[0].Id == (byte)UserTypes.SuperAdmin)
                    {
                        var sub = await created.GetAsync();
                        data = sub.ToList();
                    }
                    else if (token.UserTypes[0].Id == (byte)UserTypes.InstituteAdmin)
                    {
                        data = await created.FilterListAsync
                                            (x =&gt; x.InstituteId == token.InstituteID);
                    }
                    else
                    {
                        data = await created.FilterListAsync(x =&gt;
                                            x.InstituteId == token.InstituteID &amp;&amp; x.CampusId == token.CampusID);
                    }
                }
            }
            catch (Exception e)
            {
                
            }
            return data;
        }

答案5

得分: 0

根据您的评论,我尝试重新编写您的示例,希望这能帮助您。如果需要更多明确信息,请随时提问。

class Program
{
    static void Main(string[] args)
    {
        var objFactory = new MyFactory();
        // 获取并强制转换返回对象
        A a1 = (A)objFactory.ConsolidatedMethod("Condition 1 for Objct A", "xxx");

        // 或直接分配给基础对象
        IOutput a2 = objFactory.ConsolidatedMethod("Condition 2 for Objct A", "yyyy");

        // 使用匿名对象
        var b1 = objFactory.ConsolidatedMethod("Condition 1 for Objct B", "mmmm");

        var nullcheck1 = objFactory.ConsolidatedMethod("null conditionj", "i'm null");
    }
}

interface IOutput
{
}

class A : IOutput
{
    public A(string objParam)
    {
    }
}

class B : IOutput
{
    public B(string objParam)
    {
    }
}

class NullOutput : IOutput
{
    public NullOutput(string objParam)
    {
    }
}

class MyFactory
{
    /// <summary>
    /// 演示
    /// </summary>
    /// <param name="arg">根据您的需求使用此参数</param>
    /// <param name="objparam">根据您的需求使用此参数</param>
    /// <returns>IOutput</returns>
    public IOutput ConsolidatedMethod(string arg, string objparam)
    {
        IOutput _output = default;

        if (arg == "Condition 1 for Objct A")
            _output = new A(objparam);
        else if (arg == "Condition 2 for Objct A")
            _output = new A(objparam);
        else if (arg == "Condition 1 for Objct B")
            _output = new B(objparam);
        else if (arg == "Condition 2 for Objct B")
            _output = new B(objparam);
        else
            _output = new NullOutput(objparam);

        return _output;
    }
}
英文:

According to your comment, I tried to rewrite your sample, hope this will help you. ask freely if you need more clarity.

class Program
{
    static void Main(string[] args)
    {
        var objFactory = new MyFactory();
        // Get and cast return object
        A a1= (A) objFactory.ConsolidatedMethod(&quot;Condition 1 for Objct A&quot;, &quot;xxx&quot;);

        // Or Directly assian to base object
        IOutput a2 = objFactory.ConsolidatedMethod(&quot;Condition 2 for Objct A&quot;, &quot;yyyy&quot;);

        // use anonymous object
        var b1= objFactory.ConsolidatedMethod(&quot;Condition 1 for Objct B&quot;, &quot;mmmm&quot;);

        var nullcheck1 = objFactory.ConsolidatedMethod(&quot;null conditionj&quot;, &quot;i&#39;m null&quot;);
    }
}

interface IOutput
{
}

class A : IOutput
{
    public A(string objParam)
    {
    }
}

class B : IOutput
{
    public B(string objParam)
    {
    }
}

class NullOutput : IOutput
{
    public NullOutput(string objParam)
    {
    }
}

class MyFactory
{
    /// &lt;summary&gt;
    /// Demo 
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;arg&quot;&gt;you can use this based on your requirement &lt;/param&gt;
    /// &lt;param name=&quot;objparam&quot;&gt;you can use this based on your requirement &lt;/param&gt;
    /// &lt;returns&gt;IOutput&lt;/returns&gt;
    public IOutput ConsolidatedMethod(string arg, string objparam)
    {
        IOutput _output=default;

        if (arg == &quot;Condition 1 for Objct A&quot;)
            _output = new A(objparam);
        else if (arg == &quot;Condition 2 for Objct A&quot;)
            _output = new A(objparam);
        else if (arg == &quot;Condition 1 for Objct b&quot;)
            _output = new B(objparam);
        else if (arg == &quot;Condition 2 for Objct B&quot;)
            _output = new B(objparam);
        else
            _output = new NullOutput(objparam);

        return _output;
    }
}

huangapple
  • 本文由 发表于 2020年8月11日 23:07:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63361066.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定