4

クラスをインスタンス化する必要がある MSBuild タスクを使用しています。このクラスにはもともとパラメーターなしのコンストラクターが 1 つしかなかったため、必要な MSBuild タスクはクラスをインスタンス化するための型名だけでした。これで、特定のコンストラクターに対してタスクを実行するユースケースができましたが、これを一般的な方法で処理する方法がわかりません。のさまざまなフレーバーをインスタンス化する必要があるとしますClassA:

public class ClassA
{
    public ClassA() { }
    public ClassA(int someArgument) { }
    public ClassA(int someArgument, bool someOtherArgument) { }
}

元のタスクは次のようになります。

<DoSomethingTask Assembly="ContainsClassA.dll" Type="ClassA" />

私の理想的なタスクは次のようなもので、引数としてプリミティブ型を持つ任意のコンストラクターを呼び出すことができます。

<DoSomethingTask Assembly="ContainsClassA.dll" Type="ClassA">
    <ConstructorArgs>
        <Arg type="int">1</Arg>
        <Arg type="bool">True</Arg>
    </ConstructorArgs>
</DoSomethingTask>

このタイプの機能を取得するために何を検索すればよいか、私は非常に迷っています。文字列プロパティを呼び出しConstructorArgsて、必要な形式を使用して解析するなどのことができますが、よりクリーンなものが存在することを願っています。ご協力いただきありがとうございます。

編集 - 誰かが疑問に思っている場合に備えて、私が変更しようとしている実際のタスクは、インスタンス化された Entity Framework DbContext に基づいて事前生成されたビューを作成します。さまざまなコンストラクターを持つ独自の DbContext サブクラスがあり、ビューの生成中に特定のコンストラクターを呼び出せるようにしたいと考えています。

4

1 に答える 1

0

リフレクションを使用して、DBContext サブクラスのコンストラクターを取得することができます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace TaskClass
{
    // Class to be created
    public class MyDbContext
    {
        public int ConstructorArg1 { get; set; }
        public string ConstructorArg2 { get; set; }

        public MyDbContext() { }

        public MyDbContext(int constructorArg1)
        {
            ConstructorArg1 = constructorArg1;
        }

        public MyDbContext(int constructorArg1, string constructorArg2)
        {
            ConstructorArg1 = constructorArg1;
            ConstructorArg2 = constructorArg2;
        }       
    }

    // MSBuild custom task
    public class DoSomethingTask : Task
    {
        public override bool Execute()
        {
            var taskParameters = new TaskParametersInfo();
            taskParameters.ExtractTaskParametersInfo(this);

            var type = typeof(MyDbContext);
            ConstructorInfo ctor = type.GetConstructor(taskParameters.Types.ToArray());

            if (ctor == null)
            {
                // If the constructor is not found, throw an error
                Log.LogError("There are no constructors defined with these parameters.");
                return false;
            }

            // Create your instance
            var myDbContext = (MyDbContext)ctor.Invoke(taskParameters.Values.ToArray());

            return true;
        }

        public int ConstructorArg1
        {
            get;
            set;
        }

        public string ConstructorArg2
        {
            get; 
            set;
        }

        public string ConstructorArg3
        { 
            get; 
            set; 
        }

        // Class to handle the task's parameters
        internal class TaskParametersInfo
        {
            public List<Type> Types { get; set; }
            public List<object> Values { get; set; }

            public TaskParametersInfo()
            {
                Types = new List<Type>();
                Values = new List<object>();
            }

            public void ExtractTaskParametersInfo(Task task)
            {
                foreach (var property in task.GetType().GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance))
                {
                    var propertyValue = property.GetValue(task, null);
                    if (propertyValue != null)
                    {
                        Types.Add(property.PropertyType);
                        Values.Add(propertyValue);
                    }
                }
            }
        }
    }
}

msbuild プロジェクトにタスクをインポートします。

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Project ToolsVersion="4.0" defaultTarget="DoSomething" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="TaskClass.DoSomethingTask" 
        AssemblyFile="TaskClass\TaskClass\bin\Debug\TaskClass.dll"/>
  <Target Name="DoSomething">
    <DoSomethingTask ConstructorArg1="123" ConstructorArg2="Are u talking to me?" />
  </Target>
</Project>

お役に立てれば。

于 2013-02-21T15:35:07.423 に答える