ここが結構難儀したところです。

事前バインドできる VB6 や VBA ではインターフェイスをキッチリ作っておけばよいのですが、遅延バインドでは、フィールドをアクセスするつもりが OraDynaset のメソッドとして検索されるので、それに対応したメソッドを作ってあげる必要があります。

クラスインターフェイスのタイプは、コイツだけ AutoDispatch になります。
(OraDatabase も Parameters を実装するときは、同様です。)

using System;
using System.Data;
using System.Runtime.InteropServices;

namespace OracleInProcServerForVBS
{

    [ComVisible(true)]
    [Guid(OraDynasetClass.InterfaceId)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface OraDynaset : IDisposable
    {
        [DispId(0)]
        OraFields Fields { get; }
        int RowPosition { get; }
        void MoveFirst();
        void MoveNext();
        bool EOF { get; }
        bool BOF { get; }
        int RecordCount { get; }
    }

    [ComVisible(true)]
    [Guid(OraDynasetClass.ClassId)]
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    public class OraDynasetClass : OraDynaset
    {
        public const string ClassId = "B4BFBBF8-6548-44AE-9A0D-9D8FC7CA9479";
        public const string InterfaceId = "01F3CFC1-5D98-48D8-85B5-6699079C5508";

        private DataTable m_DataTable;
        private OraFields m_Fields;
        private int m_RowIndex = -2;

        internal OraDynasetClass(DataTable dt) {
            m_DataTable = dt;
            m_Fields = new OraFields(this, dt.Columns);
            MoveFirst();
        }

        OraFields OraDynaset.Fields {
            get {
                return m_Fields;
            }
        }

        public void Dispose() {
            if (m_DataTable != null) {
                m_DataTable.Dispose();
                m_DataTable = null;
            }
        }

        public int RowPosition {
            get {
                return RowIndex + 1;
            }
        }

        private int RowIndex {
            get {
                return m_RowIndex;
            }
            set {
                switch (value) {
                    case -2:
                    case -1:
                        m_RowIndex = value;
                        break;
                    default:
                        if (value < 0 || value > m_DataTable.Rows.Count) {
                            throw new InvalidOperationException();
                        }
                        m_RowIndex = value;
                        break;
                }
            }
        }

        public void MoveFirst() {
            RowIndex = 0;
        }

        public void MoveNext() {
            RowIndex++;
        }

        public bool EOF {
            get {
                return (RecordCount == 0 || RowIndex < -1 || RowIndex >= RecordCount);
            }
        }

        public bool BOF {
            get {
                return (RecordCount == 0 || RowIndex < 0);
            }
        }

        public int RecordCount {
            get {
                return m_DataTable.Rows.Count;
            }
        }

        internal DataRow CurrentRow {
            get {
                if (EOF || BOF) {
                    return null;
                }
                return m_DataTable.Rows[RowIndex];
            }
        }

        // 遅延バインドのために実装

        public OraField this[object Index] {
            get {
                return m_Fields[Index];
            }
        }

        public object Fields(object Index = null) {
            if (Index == null) {
                return m_Fields;
            }
            return m_Fields[Index];
        }

    }
}



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2020-04-14 (火) 16:08:57 (42d)