
log4net.dllの参照を1クラスのみに絞り、他のログ出力有りのクラス、関数では、参照する1クラスを経由してLogManager.GetLogger関数で実体化されたILogを取得し、ログ出力を行いたく考えています。
そのため、dynamic型で受けて使用するようにしてみたのですが、出力結果としてフォーマットの%Cが「?」、%Mが「CallSite.Target」と出てしまい、完全修飾子名、メソッド名の出力ができません。
同じ流れのまま、dynamic型をやめ、ILogで受けるようにしてみると、%C、%Mが正常に出ていることが確認できました。
dynamic型から別の型に変えれば解決するものなのか、何かしらの変換を掛ければ使えるのかなどがわかりませんでした。
ILog型は基本的に1クラス1個管理が望ましいような話も見かけたのですが、静的参照しているlog4netのFileNotFoundExceptionなどをキャッチしたい都合もあり、クラス分けを試みた次第です。
どうかご教授の程、お願いいたします。
<環境>
VisualStudio2015 C#
log4netバージョン:2.0.8
<サンプルコード>
(メインのcsファイル)
public class main()
{
public void start()
{
dynamic logger = logMaster.getLogger(MethodBase.GetCurrentMethod().DeclaringType);
logger.Info("開始");
・・・省略・・・
logger.Info("終了");
}
}
(同プロジェクト内のlog4net参照用csファイル)
public class logMaster()
{
public static dynamic getLogger(Type type)
{
dynamic logger = null;
try
{
logger = createLogger(type);
return logger;
}
catch(FileNotFoundException)
{
return logger;
}
}
private static dynamic createLogger(Type type)
{
return LogManage.GetLogger(type);
}
}
<ログフォーマット>
"%d [%-5level] - %t %C %M %m%n"
No.5ベストアンサー
- 回答日時:
log4net.dllがない時に、実装側が意識することなくコードしたいなら、log4netを利用するクラスを更にラッピングして処理を委譲する形にならできそうですね。
ラッピングするので、必要な処理を全部記述しなければなりません。
【MyLog4Net.cs】
using log4net;
using System;
namespace ClassLibrary1
{
class MyLog4Net
{
private ILog log = null;
private MyLog4Net(ILog log)
{
this.log = log;
}
public static MyLog4Net GetLogger(Type type)
{
var log = LogManager.GetLogger(type);
return new MyLog4Net(log);
}
public void Info(string message)
{
this.log.Logger.Log(type, log4net.Core.Level.Info, message, null);
}
}
}
【MyLog.cs】
using System;
using System.Collections.Generic;
using System.IO;
namespace ClassLibrary1
{
class MyLog
{
private static Dictionary<Type, MyLog> logList = new Dictionary<Type, MyLog>();
private MyLog4Net log = null;
private MyLog(Type type)
{
try
{
this.log = MyLog4Net.GetLogger(type);
}
catch (FileNotFoundException)
{
// 意図的に何もしない
}
}
public static MyLog GetLogger(Type type)
{
if (MyLog.logList.ContainsKey(type))
{
return MyLog.logList[type];
}
MyLog log = new MyLog(type);
MyLog.logList.Add(type, log);
return log;
}
public void Info(string message)
{
if (this.log == null)
{
return;
}
this.log.Info(typeof(MyLog), message);
}
}
}
【Main.cs】
namespace ClassLibrary1
{
public class Main
{
public void Start()
{
MyLog log = MyLog.GetLogger(typeof(Main));
log.Info("hoge");
MyLog log2 = MyLog.GetLogger(typeof(Main));
log.Info("fuga");
}
}
}
【Program.cs】
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
(new ClassLibrary1.Main()).Start();
}
}
}
ちなみにdynamicで行おうとすると、内部的にはCallSiteというクラスによって処理されるため、%C, %Mがそのように出てしまいます。
調べてみましたが、素のままではこれは解決できそうにはありませんでした。
log4net.dllが得られなかった時にも処理を継続したいと考えており、上記方法で対応することが仰々しくなって煩雑なようであれば、dynamicによる対応でもいいかなとは思います。
でもその時は、%C, %Mは諦めて、メッセージに、発生したクラスおよびメソッドを記述する形を取るしかなさそうですね。
ラッピングは自分も考えましたが、設計・実装の手間的にどうしたものか。。。って感じでしたね。
再考してみようとは思います。
とりあえず%C、%Mを%mで収束する方向で考えてみます。
長々とありがとうございました。
No.4
- 回答日時:
> 作成してるのは、アプリではなくDLLになります。
> そのため、私の方のサンプルのstart関数が、インターフェース関数になり、インターフェース
> 関数でもログを出すことから、File.Existsの事前チェックができません。
ログが出力できる状態にない場合があるのに、ログを出力しようとするんですか?
また、実際にlog4net.dllが得られず例外となった時、そのDLLの呼び出したメソッドは、ログを出力しないだけでそれ以外の動作は正常に動作させたいとか、そういうことなのでしょうか?
No.3
- 回答日時:
特殊な動作をその場で必要としないなら、StartupValidatorのようなクラスはいらないかもです。
サンプルコードありがとうございます。
ただ、説明不足でした。すみません。
作成してるのは、アプリではなくDLLになります。
そのため、私の方のサンプルのstart関数が、インターフェース関数になり、インターフェース関数でもログを出すことから、File.Existsの事前チェックができません。
start関数がFile.Existsを敷いても、ILogを使った時点でFile.Exists前にFileNotFoundがアプリに返されてしまいますし・・・。
DLLは完全提供品となり、アプリは別口の開発となり、本主旨としては「アプリ側への例外を避ける」になります。
No.2
- 回答日時:
> 本目的としましては、外部ライブラリが存在しない場合は、専用のエラーコードを呼び出し元
> に返すというところにあります。
これは、参照すべきlog4net.dllが配置場所に存在するか、という検証を事前に行い、NGなら例外を発行すれば済むのではないでしょうか?
とどのつまり、log4netが必要になるより以前に、ファイルがあることが担保できればいいわけなので。
1.エントリポイントの走行で、あるべきdllを検証する。
2.検証が通ったら、メインクラスをインスタンス化するなどして処理を行う。
みたく。
参照設定しているdllは、初めて使われるクラスなどが利用された時に初めて読み込みに行きます。
そのため、dllを必要としていない間は、対象dllに対するエラーは発生しません。
なので、なんでもかんでもエントリポイントだかでやろうとしているのが悪いだけでは。
【Program.cs】
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
try
{
StartupValidator.Validate();
MainClass.Start();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
【StartupValidator.cs】
using System.IO;
namespace ConsoleApp1
{
static class StartupValidator
{
public static void Validate()
{
var directory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
var filePath = Path.Combine(directory, @"log4net.dll");
if (!File.Exists(filePath))
{
throw new FileNotFoundException("log4net.dllが存在しない");
}
}
}
}
【MainClass.cs】
using log4net;
namespace ConsoleApp1
{
static class MainClass
{
public static void Start()
{
ILog logger = LogManager.GetLogger(typeof(Program));
logger.Info("hoge");
}
}
}
No.1
- 回答日時:
そもそも論になりますが・・・
> log4net.dllの参照を1クラスのみに絞り、他のログ出力有りのクラス、関数では、参照する1
> クラスを経由して
それらがすべて同一プロジェクトにあるのならば、そうする必然性がわかりません。
また、別プロジェクトであったとしても、ラッピングを要するならば、ラッピングクラスが存在するプロジェクトを参照設定する必要があり、log4net.dllを参照設定することと差がありません。
ILogクラスまたはラッピングクラスしか返ってきようがないのに、インテリセンスも効かなくなり、dynamicの用途として間違っていると思います。
ご回答ありがとうございますm(__)m
仰る事は凄く分かります・・・。
本目的としましては、外部ライブラリが存在しない場合は、専用のエラーコードを呼び出し元に返すというところにあります。
元々は、mainクラス側にILogのメンバ変数を作り、コンストラクタでGetLogger関数を呼んでいたのですが、コンストラクタでは戻り値を返せません。
そして、メンバ変数を辞め、start関数でILogのローカル変数を作る形にした場合は、1ステップも進むこと無く、catchができません。
そのため、どこかでcatchを敷いて、ようやくdll参照に持っていこうとした結果がサンプルです。
GetLogger関数は、あいにく静的メンバということもあり、動的DLL読み込みでインスタンスを作って、という訳にも行かないなどもあり、クラスを別途としようとした結果となります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- JavaScript アップロードファイルの種類によって処理を分岐させたいのですが書き方が分からずアドバイスお願いします 4 2023/06/17 19:12
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- その他(パソコン・周辺機器) タブレットで使用するUSBメモリについて 7 2022/05/26 14:27
- C言語・C++・C# Windows Formアプリからコンソールを呼び出して文字を出力させたい 8 2023/05/09 10:53
- JavaScript jqueryを使ったスムーススクロールのコードを書いたのですが、HTMLコード内にある、a butt 2 2022/04/14 10:59
- JavaScript clear機能を失わずにファイルアップロード機能を作成したい 3 2023/06/10 16:12
- JavaScript Javascript初心者|jQueryの.val()で値を取得し複数の要素を連結させる方法知りたい 2 2022/06/02 12:06
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
クラス間でのデータ参照
-
範囲外の数値を代入したらエラ...
-
C#でほかのファイルにある自作...
-
関数内の変数に<summary>コメン...
-
ClassLoader.getSystemResource...
-
アップキャスト、ダウンキャス...
-
ひとつのファイルにクラスは1つ?
-
アブストラクトとインターフェ...
-
c++,ある関数のクラスから別の...
-
C#にて別クラスの関数を使いたい
-
”main”NoClassDefFoundErro...
-
Java
-
違うクラスからの変数の共有化
-
C++でfriendクラスにしているの...
-
構造 他のクラスの構造体を別...
-
継承したクラス側のクラス名の取得
-
フォームBeanのメソッド内で変...
-
java-別クラスの変数の使い方を...
-
デシリアライズでオブジェクト...
-
FilterReader クラスのカスタム...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数内の変数に<summary>コメン...
-
C#でほかのファイルにある自作...
-
C#にて別クラスの関数を使いたい
-
クラス間でのデータ参照
-
import と extends について
-
c++,ある関数のクラスから別の...
-
範囲外の数値を代入したらエラ...
-
C#のクラスライブラリでメッセ...
-
C++でfriendクラスにしているの...
-
ひとつのファイルにクラスは1つ?
-
無名パッケージからのインポート
-
継承したクラス側のクラス名の取得
-
visual studioのデザイナ画面で...
-
a href="..." とServlet
-
Java リフレクションについて
-
構造 他のクラスの構造体を別...
-
ASP Pageの孫継承のPage_Load
-
別ファイルのclassの読み込みに...
-
オーバーロードしたメンバ関数...
-
実行可能jarファイルのファイル...
おすすめ情報