はじめまして、行き詰ってしまったため初めて投稿させていただきます。
言葉で伝えるのが苦手なため箇条書き気味となりますがご容赦ください。
・やりたいこと
IISでホスティングするサービス(.svc)を1つ用意する。
クライアントから利用したいアセンブリ名とクラス名をサービスに渡して、サーバー側のdllをサービスから動的に参照して、サーバー側のdll内にあるメソッドを実行したい。
・やっていたこと
クライアントから利用したいアセンブリ名とクラス名をサービスに渡して、サービス内でアセンブリを動的参照し、参照できたらアセンブリよりクラス名のTypeを取得してサービスホストをOpenする。
新たにOpenされたホストのサービスをクライアント側からChannelFactoryを用いて利用して、利用が終わったらホストをCloseする。
動的にホストをOpenしたりCloseする処理は全てIISにホストしているサービスが行うものとする。
・全体の構成
3層構造のプログラムをイメージしています。ユーザー層、ビジネスロジック層、データベース層(SQLサーバー)
今回質問させていただいています内容はユーザー層とビジネスロジック層の間での問題になります。
プログラムはメニューから子のプログラムが起動するようになっており、子のプログラムが画面表示(UI)のdll、ビジネスロジックのdll、ビジネスロジックと通信するためのインターフェイスのdllをもっています。
・問題点
ホストを動的にOpenする際に以下のエラーがでます。
HTTP が URL http://+:80/ベースアドレス/動的に作成したホスト固有のアドレス/ を登録できませんでした。プロセスにこの名前空間へのアクセス権がありません (詳細については、http://go.microsoft.com/fwlink/?LinkId=70353 (英語ページの可能性があります) を参照してください)。
上記のエラーはIISにホストしないで、セルフホストを行うためのコンソールプログラムを作成した場合は発生しません。IISにホスティングした場合のみエラーが発生し、セルフホストの場合はエラーはなく、正しく動作していました。
以下はサービスの内容です。
Public Function MakeTempHost(ByVal assName As String, ByVal assClassName As String, ByVal userName As String) As String Implements IMakeHost.MakeTempHost
Dim renban As Integer = 1
Dim errarStr As String = ""
'既にリスナがあるか確認して、ホストアドレスを1から連番で作成する
Do While _saveceHash.ContainsKey("http://[ベースアドレス]/" & assName & assClassName & userName & CStr(renban))
renban += 1
Loop
Dim hostAdress As String
hostAdress = "http://[ベースアドレス]/" & assName & assClassName & userName & CStr(renban)
'インストールディレクトリ取得
Dim path As String = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath
Try
'動的にdllを参照する
' DLL を指定して、動的にアセンブリをロードする。
'サービス部分(ビジネスロジック)をロードします。
Dim assem As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom(path & "\bin\" & assName & "BL.dll")
'サービスを呼ぶためのインターフェイスをロードします。
Dim Iassem As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom(path & "\bin\" & assName & ".dll")
' 指定のアセンブリから、指定クラスのType オブジェクトを取得。
Dim AssType As Type = assem.GetType(assName & ".BL" & assClassName)
Dim IAssType As Type = Iassem.GetType(assName & ".I" & assClassName)
'一時的なホストを作成する
Dim bind As New BasicHttpBinding
Dim tempHost As ServiceHost = New ServiceHost(AssType,New Uri(hostAdress))
tempHost.AddServiceEndpoint(IAssType, bind, hostAdress)
tempHost.Open()
_saveceHash.Add(hostAdress, tempHost)
Catch ex As Exception
Return ex.Message
End Try
'決定したホストアドレスを返す
Return hostAdress
End Function
クライアントから呼び出す時は以下のようにしていました。
Dim hostAdress As String = ""
Dim endPoint As New EndpointAddress("http://[ベースアドレス]")
Dim mainProxy As IMakeTempHost
mainProxy = ChannelFactory(Of IMakeTempHost).CreateChannel(_bainding, endPoint)
' WCFサービスのメソッドを呼び出します。
hostAdress = mainProxy.MakeTempHost(assName, assClassName, userName)
' エンドポイントを作成します。
Dim endPoint As New EndpointAddress(hostAdress)
' プロキシを作成します。
'Tは使いたいサービスのインターフェイスです
Dim proxy As T = ChannelFactory(Of T).CreateChannel(_bainding, endPoint)
’proxyを使って使いたいメソッドを呼び出します。
バインディングはBasicHttpBindingを利用しています。
やっている内容がそもそも効率的な動作なのかもわかっていません。
エラー内容の解決以外にも、設計上違うアプローチのほうが効率的などアドバイスいただけたら助かります。