住んでいた-古代の恐竜時代のコードでした
与えられた: 地獄は 、同じ「ああ何」製品の16の異なるバージョンで働くコーダーです。 COM、相互運用性、インターフェース、実装、要因のあるシグナルトーン、アンチパターンのあるパターン、モジュール、およびオープンソースのその他の欠陥。 標準セット。 彼は成長し、夫となり、そのkodniknikを7年熟成させました。 これまで、別の修正で16モジュールの一括コピー/貼り付けが修正されませんでした。 誰もが興味を持っている場合-変更のためにforeach on 。
苦しんだ後、私たちは研究を行いました。 コピーと貼り付けは95%同一であり、相互運用機能からのパッケージの名前のみが異なります。
ラッパーで何百もの関数をラップしないように、またこれらのラッパーのパンチング/ボクシングハンドルをラップしないように書くことは可能ですか?
動的キーワードがあります!
そして、そのような素晴らしい眺めの地獄のパスタ
標準的な恐怖
public abstract class Application : IDisposable { public abstract void Close(); public abstract Document CreateDocument(); public abstract Document OpenDocument(string doc_path); // 200 // , void IDisposable.Dispose() { Close(); } } public class ClientApplication : Application { protected ClientApplication(){ string recovery_path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); recovery_path = Path.Combine( recovery_path, String.Format( @"...\Version {0}\en_GB\Caches\Recovery", Version)); try { foreach (string file in Directory.GetFiles(recovery_path)){ try { File.Delete(file); } catch { } } } catch {} // } public override void Close() { if (Host != null) { Marshal.ReleaseComObject(Host); Host = null; } } } public class ClientApplication7_5 : ClientApplication { protected ClientApplication7_5() { Type type = Type.GetTypeFromProgID("....Application." + Version, true); _app = Activator.CreateInstance(type) as Interop75.Application; Host = app; // ... } public override Document CreateDocument() { return new ClientDocument7_5(this, _app.Documents.Add()); } public override Document OpenDocument(string doc_path) { return new ClientDocument7_5(this, _app.Open(doc_path, true, ...) as Interop75.Document); } // 200 public override ComObject Host { get { return _app; } set { _app = value as Interop75.Application; } } private Interop75.Application _app; // - } public class ServerApplication : Application { public ServerApplication() {} ... } // , 8
不要になり、この不名誉を使用したコード
var app = Factory.GetApplication(); var doc = app.Documents.Add(); doc.DocumentPreferences.PreserveLayoutWhenShuffling = false; doc.DocumentPreferences.AllowPageShuffle = true; doc.DocumentPreferences.StartPageNumber = 1;
変わりません。
利益? やれやれ! 半ば生成されたホラー映画のダースメガバイトは、ゴミ箱に正常にスローされます。 新しいバージョンのサポートは大幅に簡素化されています。
リトアニアの休日「オブロマチス」
テストを実行します。 バム!
そのcom睡状態のすべての呼び出しがOKを返すまで、それは非常にうまくいきません。 しかし、テストを待つ価値があった
try { var app = Factory.GetApplication(); var doc = app.Documents.Add(); doc.DocumentPreferences.PreserveLayoutWhenShuffling = false; doc.DocumentPreferences.AllowPageShuffle = true; doc.DocumentPreferences.StartPageNumber = -1; } catch (COMException ok) { .... // "" } catch(Exception bad) { ... // , bad - NullReferenceException StackTrace!!! }
ショック、スキャンダル、陰謀、調査。 誰もが興味を持っている場合-マイクロソフトで確認されたバグは5.0以前に修正されます。 悲しいと退屈。
探究心は休息を与えません-結局、あなたがinteropesを通過するならば、それはすべてあるべきですか? デバッガーは、ドキュメントの種類をSystem .__ ComObjectとして表示します。 しかし、RCWはどうですか? 理解できませんでしたか?
テストを変更します
try { var app = Factory.GetApplication(); var doc = app.Documents.Add() as Interop75.Document; doc.DocumentPreferences.PreserveLayoutWhenShuffling = false; doc.DocumentPreferences.AllowPageShuffle = true; doc.DocumentPreferences.StartPageNumber = -1; } catch (COMException ok) { .... // } catch(Exception bad) { ... }
そして...テストに合格しました。
仮説は興味深いです。 それで、タイプが分からないのではないでしょうか? 確認する
var app = Factory.GetApplication(); var doc = app.Documents.Add(); var typeName = Microsoft.VisualBasic.Information.TypeName(doc);
うーん かなり自分自身に。
アイデアは終わりました。
しかし、待ってください-生はありますか? 私たちは見て、喫煙し、難読化のスキルを賞賛します。 ここから開始: __ComObject ここにシームレスに流れました: Type.cs。 出来上がり 喫煙の過程で理解が得られました。したがって、明らかにこれらのas睡状態をさまざまな方法で処理している場所がいくつかあります。 交換するとどうなりますか
doc.DocumentPreferences.StartPageNumber = -1;
に
Type type = doc.DocumentPreferences.GetType(); type.InvokeMember("StartPageNumber", BindingFlags.SetProperty, null, doc.DocumentPreferences, new object[] { -1 });
理論的には-何も?
小間物と枢機inalは力です
そして、ここで変化しています。 テストに再び合格しました。 そして何をすべきか? このような美しいコードをパスタに変えても笑顔になることはなく、たくさんあります。
夕方遅く、私は状況を密かにトロールして鎮圧しようとしています-反射神経のスピーカーの認識をスリップできますか? 私はまだ考えを理解しています-そして、これは考えです!
やってみます。
ComWrapperはDynamicObjectを拡張します
public class ComWrapper : DynamicObject { public ComWrapper(object comObject) { _comObject = comObject; _type = _comObject.GetType(); } public object WrappedObject { get { return _comObject; } } // // + public override bool TryGetMember(GetMemberBinder binder, out object result) { result = Wrap(_type.InvokeMember(binder.Name, BindingFlags.GetProperty, null, _comObject, null)); return true; } public override bool TrySetMember(SetMemberBinder binder, object value) { _type.InvokeMember( binder.Name, BindingFlags.SetProperty, null, _comObject, new object[] { Unwrap(value) } ); return true; } // public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { result = Wrap(_type.InvokeMember( binder.Name, BindingFlags.InvokeMethod, null, _comObject, args.Select(arg => Unwrap(arg)).ToArray() )); return true; } // - private object Wrap(object obj) { return obj != null && obj.GetType().IsCOMObject ? new ComWrapper(obj) : obj; } private object Unwrap(object obj) { ComWrapper wrapper = obj as ComWrapper; return wrapper != null ? wrapper._comObject : obj; } // + private object _comObject; private Type _type; }
素晴らしい-それはそれ自体ですべてを行い、正常に機能します。必要なのは、それらをFactory.GetApplication()の結果でラップすることです。 すぐそこにラップ。 本当にニュアンスがあります-コレクションを忘れてしまいました。 それで少し後に彼らはこれを追加しました:
いくつかのバックアップ
// private IEnumerable Enumerate() { foreach (var item in (IEnumerable)_comObject) yield return Wrap(item); } // enumerable public override bool TryConvert(ConvertBinder binder, out object result) { if (binder.Type.Equals(typeof(IEnumerable)) && _comObject is IEnumerable) { result = Enumerate(); return true; } result = null; return false; } // , . public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { if (indexes.Length == 1) { dynamic indexer = _comObject; result = Wrap(indexer[indexes[0]]); return true; } result = null; return false; } public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) { if (indexes.Length == 1) { dynamic indexer = _comObject; indexer[indexes[0]] = Unwrap(value); return true; } return false; }
今が勝利です。
突然誰かが重宝します。