プラグインクラス属性

Namespace: fvalgcli
Assembly: fvalgcli (in fvalgcli.dll) Version: 3.1.0.0 (3.1.0.11)

Syntax

C#
public class FvPluginClassAttribute : Attribute
Visual Basic
Public Class FvPluginClassAttribute
	Inherits Attribute

Remarks

実行対象のクラスを指定する属性です。

アセンブリとクラスの関係は 1:N であることを想定しています。
ユニットテストやベンチマークを対象にします。


各属性とアセンブリやクラスの関係:
属性アセンブリとの関係クラスとの関係説明
FvPluginSetupAttribute11初期化処理を保有しているクラス及びメソッド
FvPluginTearDownAttribute11解放処理を保有しているクラス及びメソッド
FvPluginClassAttributeN1実行対象の処理を保有するクラス
FvPluginPrepareAttributeN1処理前の準備
FvPluginRestoreAttributeN1処理後の復元
FvPluginExecuteAttributeNN実行対象の処理

Examples

トピック:


属性を読み込んで実行する処理:

ここでは GetExecutingAssembly で現在のアセンブリを取得してクラスとメソッドを抽出していますが、 アセンブリを動的ロードする場合は LoadLoadFile を使用します。

C# Copy imageCopy
// $Revision: 1.1 $

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using fvalgcli;

namespace User.SampleCode
{
    /// <summary>
    /// ホストクラス.
    /// </summary>
    class Host
    {
        /// <summary>
        /// エントリポイント.
        /// </summary>
        /// <param name="args"></param>
        public static void _Main(string[] args)
        {
            // 初期化.
            Setup();

            // 実行.
            Execute();

            // 解放.
            TearDown();
        }

        /// <summary>
        /// 初期化.
        /// </summary>
        public static void Setup()
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            Type[] types = asm.GetTypes();
            foreach (Type type in types)
            {
                // [FvPluginSetup] 属性が付加されたクラスか否かの検査.
                object[] attrs = type.GetCustomAttributes(typeof(FvPluginSetupAttribute), true);
                if (attrs.Length == 0) continue;

                // メソッド情報の抽出及び実行.
                // ※注) static 関数である前提で関数を呼び出しています.
                MethodInfo[] methods = type.GetMethods();
                foreach (MethodInfo method in methods)
                {
                    attrs = method.GetCustomAttributes(typeof(FvPluginSetupAttribute), true);
                    if (attrs.Length > 0)
                    {
                        Console.WriteLine(type.Name + "." + method.Name);
                        method.Invoke(null, null);
                    }
                }
            }
        }

        /// <summary>
        /// 解放.
        /// </summary>
        public static void TearDown()
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            Type[] types = asm.GetTypes();
            foreach (Type type in types)
            {
                // [FvPluginTearDown] 属性が付加されたクラスか否かの検査.
                object[] attrs = type.GetCustomAttributes(typeof(FvPluginTearDownAttribute), true);
                if (attrs.Length == 0) continue;

                // メソッド情報の抽出及び実行.
                // ※注) static 関数である前提で関数を呼び出しています.
                MethodInfo[] methods = type.GetMethods();
                foreach (MethodInfo method in methods)
                {
                    attrs = method.GetCustomAttributes(typeof(FvPluginTearDownAttribute), true);
                    if (attrs.Length > 0)
                    {
                        Console.WriteLine(type.Name + "." + method.Name);
                        method.Invoke(null, null);
                    }
                }
            }
        }

        /// <summary>
        /// 実行.
        /// </summary>
        public static void Execute()
        {
            ResolveEventHandler asm_resolving = new ResolveEventHandler(AssemblyResolving);
            ResolveEventHandler type_resolving = new ResolveEventHandler(TypeResolving);

            try
            {
                AppDomain.CurrentDomain.AssemblyResolve += asm_resolving;
                AppDomain.CurrentDomain.TypeResolve += type_resolving;

                Assembly asm = Assembly.GetExecutingAssembly();
                Type[] types = asm.GetTypes();
                foreach (Type type in types)
                {
                    // [FvPluginClass] 属性が付加されたクラスか否かの検査.
                    object[] attrs = type.GetCustomAttributes(typeof(FvPluginClassAttribute), true);
                    if (attrs.Length == 0) continue;

                    List<MethodInfo> prepares = new List<MethodInfo>();
                    List<MethodInfo> executes = new List<MethodInfo>();
                    List<MethodInfo> restores = new List<MethodInfo>();

                    // メソッド情報の抽出.
                    MethodInfo[] methods = type.GetMethods();
                    foreach (MethodInfo method in methods)
                    {
                        attrs = method.GetCustomAttributes(typeof(FvPluginPrepareAttribute), true);
                        if (attrs.Length > 0)
                            prepares.Add(method);

                        attrs = method.GetCustomAttributes(typeof(FvPluginExecuteAttribute), true);
                        if (attrs.Length > 0)
                            executes.Add(method);

                        attrs = method.GetCustomAttributes(typeof(FvPluginRestoreAttribute), true);
                        if (attrs.Length > 0)
                            restores.Add(method);
                    }

                    object instance = Activator.CreateInstance(type);

                    // 処理前の準備.
                    foreach (MethodInfo method in prepares)
                    {
                        Console.WriteLine(type.Name + "." + method.Name);
                        method.Invoke(instance, null);
                    }

                    // 処理.
                    foreach (MethodInfo method in executes)
                    {
                        Console.WriteLine(type.Name + "." + method.Name);
                        Stopwatch watch = new Stopwatch();
                        watch.Start();
                        method.Invoke(instance, null);
                        watch.Stop();
                        Console.WriteLine("{0:0.000} msec", watch.ElapsedMilliseconds);
                    }

                    // 処理後の復元.
                    foreach (MethodInfo method in restores)
                    {
                        Console.WriteLine(type.Name + "." + method.Name);
                        method.Invoke(instance, null);
                    }
                }
            }
            finally
            {
                AppDomain.CurrentDomain.AssemblyResolve -= asm_resolving;
                AppDomain.CurrentDomain.TypeResolve -= type_resolving;
            }
        }

        /// <summary>
        /// デシリアライズ時にアセンブリの解決が失敗したときに発生します。(seealso:AppDomain.CurrentDomain.AssemblyResolve)
        /// </summary>
        /// <param name="sender">送信元</param>
        /// <param name="args">アセンブリ名</param>
        /// <returns>
        ///        指定されたアセンブリ名に該当するアセンブリを返します。
        /// </returns>
        public static Assembly AssemblyResolving(object sender, ResolveEventArgs args)
        {
            string name = args.Name.Split(',')[0];
            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly assembly in assemblies)
            {
                if (name == assembly.FullName.Split(',')[0])
                    return assembly;
            }
            return null;
        }

        /// <summary>
        /// Type.GetType() で型の解決が失敗したときに発生します。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        /// <returns>
        ///        見つかったアセンブリを返します。
        /// </returns>
        public static Assembly TypeResolving(object sender, ResolveEventArgs args)
        {
            string name = args.Name.Split(',')[0];
            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            foreach (Assembly assembly in assemblies)
            {
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    if (name == type.FullName)
                        return assembly;
                }
            }
            return null;
        }
    }
}


初期化処理と解放処理:

アセンブリロード時に実行する初期化処理やアンロード時に実行する解放処理を記述します。

C# Copy imageCopy
using System;
using System.Collections.Generic;
using System.Text;
using fvalgcli;

namespace User.SampleCode
{
    /// <summary>
    /// テスト対象1: 初期化と解放を行います.
    /// </summary>
    [FvPluginSetup]
    [FvPluginTearDown]
    public class TestClass1
    {
        /// <summary>
        /// 初期化.
        /// </summary>
        [FvPluginSetup]
        public static void Setup()
        {
            api.fnFIE_setup();
        }

        /// <summary>
        /// 解放.
        /// </summary>
        [FvPluginTearDown]
        public static void TearDown()
        {
            api.fnFIE_teardown();
        }
    }
}


実行対象の処理を保有するクラス:

ユニットテストやベンチマークを記述します。

C# Copy imageCopy
using System;
using System.Collections.Generic;
using System.Text;
using fvalgcli;

namespace User.SampleCode
{
    /// <summary>
    /// テスト対象2: 実行対象の処理を保有しています.
    /// </summary>
    [FvPluginClass]
    public class TestClass2 : IDisposable
    {
        /// <summary>
        /// コンストラクタ.
        /// </summary>
        public TestClass2()
        {
        }

        /// <summary>
        /// テスト対象の画像.
        /// </summary>
        private FHANDLE TestImage = IntPtr.Zero;

        /// <summary>
        /// 実行前の準備.
        /// </summary>
        [FvPluginPrepare]
        public void Initialize()
        {
            // テスト対象の画像ファイルの読み込み.
            FHANDLE hImage = IntPtr.Zero;
            api.fnFIE_load_img_file("./testimage_rgb.png", ref hImage, f_color_img_type.F_COLOR_IMG_TYPE_UC8);
            this.TestImage = hImage;
        }

        /// <summary>
        /// 実行前の復元.
        /// </summary>
        [FvPluginRestore]
        public virtual void Dispose()
        {
            TestImage.Dispose();
        }

        /// <summary>
        /// テスト1
        /// </summary>
        [FvPluginExecute]
        public void Test1()
        {
            FHANDLE hsrc = this.TestImage;

            int type = api.fnFIE_img_get_type(hsrc);
            int channels = api.fnFIE_img_get_channels(hsrc);
            int width = api.fnFIE_img_get_width(hsrc);
            int height = api.fnFIE_img_get_height(hsrc);

            Console.WriteLine("type     = {0}", (f_imgtype)type);
            Console.WriteLine("channels = {0}", channels);
            Console.WriteLine("width    = {0}", width);
            Console.WriteLine("height   = {0}", height);

            if (type == (int)f_imgtype.F_IMG_UC8)
            {
                // 各チャネルの積算値.
                for (int ch = 0; ch < channels; ch++)
                {
                    double sum = 0;
                    SIZE_T step = api.fnFIE_img_get_step(hsrc) * sizeof(byte);
                    UCHAR_PTR adrs = api.fnFIE_img_get_ch_adrs(hsrc, ch);
                    for (int y = 0; y < height; y++)
                    {
                        for (int x = 0; x < width; x++)
                            sum += adrs[x];
                        adrs += step;
                    }
                    Console.WriteLine("ch{1}.sum  = {0}", sum, ch);
                }
            }
        }

        /// <summary>
        /// テスト2
        /// </summary>
        [FvPluginExecute]
        public void Test2()
        {
            FHANDLE target = IntPtr.Zero;
            FHANDLE test = IntPtr.Zero;
            try
            {
                // 処理.
                int width = api.fnFIE_img_get_width(TestImage);
                int height = api.fnFIE_img_get_height(TestImage);
                target = api.fnFIE_img_root_alloc(f_imgtype.F_IMG_UC8, 1, width, height);
                api.fnFIE_img_rgb_to_gray(TestImage, target, 0.299, 0.587, 0.114, 0);

                // 比較.
                bool result = false;
                api.fnFIE_load_img_file("./testimage_uc8.png", ref test, f_color_img_type.F_COLOR_IMG_TYPE_UC8);
                api.fnFIE_img_compare(target, test, ref result);
                if (result == false)
                    throw new FvException(f_err.F_ERR_INVALID_IMAGE);

                Console.WriteLine("completed.");
            }
            catch(System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                target.Dispose();
                test.Dispose();
            }
        }
    }
}


実行結果:
TestClass1.Setup
TestClass2.Initialize
TestClass2.Test1
type     = F_IMG_UC8
channels = 3
width    = 320
height   = 240
ch0.sum  = 12070920
ch1.sum  = 12222679
ch2.sum  = 12060206
9.000 msec
TestClass2.Test2
completed.
4.000 msec
TestClass2.Dispose
TestClass1.TearDown

Inheritance Hierarchy

See Also