Witam
Próbuję stworzyć nakładkę działającą w środowisku CAD (ZwCAD i AutoCAD). Każda z tych platform udostępnia .NET API z klasami o takich samych nazwach ale niestety umieszczonych w różnych namespace. Główny namespace dla ZwCAD to ZwSoft.ZwCAD... itd a dla AutoCAD Autodesk.AutoCAD... itd. Zagłębione namespace i nazwy klas są już zgodne.
Nakładka w postaci pliku dll jest wczytywana do środowiska poleceniem CAD'a netload jakis.dll i można korzystać komend w niej zawartych. Niestety przy silnym typowaniu muszę już na etapie kompilacji zadecydować z którego namespace mają być brane typy. W takim przypadku dll zrobiona dla ZwCAD'a nie zadziała w AutoCAD choć kod jest identyczny tylko przestrzeń nazw się nie zgadza. Ładując taką dll jestem w stanie sprawdzić do jakiej platformy ją wgrywam i np. wgrać dll przeznaczone dla tej konkretnej platformy. Muszę jednak tworzyć osobne dll dla ZwCAD, AutoCAD itd.
Czy jest jakiś sposób na to aby dynamicznie używać klas z namespace zależnego od rozpoznanego środowiska? Nie chcę po prostu pisać podwójnie kodu czy generować różnych dll które tak na prawdę wewnątrz są identyczne.
Typ dynamic + tworzenie obiektów przenieść do dwóch fabryk , jedna dla Autocada, druga dla ZwCada, wada: tracisz silne typowanie.
Alternatywnie możesz napisać warstwę abstrakcji, który każdy typ udostępniany przez api opakowuje w proxy które będzie pod spodem albo używało dynamica, albo statycznie decydowało z którego api skorzystać, dużo roboty to będzie, ale za to będziesz miał silne typowanie.
typeof(T).FullName // namespace and class name
https://stackoverflow.com/questions/223952/create-an-instance-of-a-class-from-a-string
neves napisał(a):
Typ dynamic + tworzenie obiektów przenieść do dwóch fabryk , jedna dla Autocada, druga dla ZwCada, wada: tracisz silne typowanie.
Alternatywnie możesz napisać warstwę abstrakcji, który każdy typ udostępniany przez api opakowuje w proxy które będzie pod spodem albo używało dynamica, albo statycznie decydowało z którego api skorzystać, dużo roboty to będzie, ale za to będziesz miał silne typowanie.
Czyli te proxy to opakowanie w moje znane klasy typów z zewnętrznych assembly powołanych jako zmienne dynamic? W takim układzie musiałbym w zasadzie przepisać całe używane przeze mnie API z cad'a i stworzyć API do API ze zmiennymi dynamic wewnątrz proxy. Chyba to jeszcze dla mnie za trudne. W dodatku wygląda że w czort roboty i łatwo się pomylić w dynamikach.
Niemniej jednak dzięki za kierunek.
Chciałbym odgrzać tego kotleta. Na jakiś czas zrezygnowałem z wieloplatformowości, ale chciałbym do tego wrócić. Nie potrafię zaimplementować tego co było napisane powyżej z powodu braku wiedzy. Czy mógłby ktoś spróbować rozwiązać problem przedstawiony na listingu :
using System;
#if ZWCAD
using ZwSoft.ZwCAD.Geometry;
#endif
#if AUTOCADCAD
using Autodesk.AutoCAD.Geometry;
#endif
using Proxy.Geometry;
// Każdy z poniższych namespace jest w innej .dll dla uproszczenia wrzucone do jednego kodu
// Jak usunąć zależność SomeNamespace od ZwSoft.ZwCAD.Geometry i Autodesk.AutoCAD.Geometry
// i pozostawić tylko zależność od Proxy.Geometry?
// Samo Proxy może być kompilowane z uwzględnieniem zdefiniowanych symboli ZWCAD lub AUTOCAD
// a jedynym źródłem typów dla modułu SomeNameSpace ( i innych ) powinien być Proxy.
// Typy do "mapowania" to całe drzewo klas, klas statycznych, struktur, atrybutów etc.
namespace SomeNamespace
{
public class SomeClass
{
public void Test()
{
Point2d point = new Point2d(); // ?
}
}
}
namespace Proxy.Geometry
{
public struct Point2d { } // ?
}
namespace ZwSoft.ZwCAD.Geometry
{
[DefaultMember("Coordinate")]
[Wrapper("ZcGePoint2d")]
public struct Point2d : IFormattable
{
public Point2d(double[] xy);
public Point2d(double x, double y);
public double this[int i] { get; }
public static Point2d Origin { get; }
public double Y { get; }
public double X { get; }
public Point2d Add(Vector2d value);
public Point2d DivideBy(double value);
public sealed override bool Equals(object obj);
public Vector2d GetAsVector();
public double GetDistanceTo(Point2d point);
public sealed override int GetHashCode();
public Vector2d GetVectorTo(Point2d point);
public bool IsEqualTo(Point2d a, Tolerance tolerance);
public bool IsEqualTo(Point2d a);
public Point2d Mirror(Line2d line);
public Point2d MultiplyBy(double value);
public Point2d RotateBy(double angle, Point2d origin);
public Point2d ScaleBy(double scaleFactor, Point2d origin);
public Point2d Subtract(Vector2d value);
public double[] ToArray();
public string ToString(IFormatProvider provider);
public sealed override string ToString();
public string ToString(string format, IFormatProvider provider);
public Point2d TransformBy(Matrix2d leftSide);
public static Point2d operator +(Point2d a, Vector2d vector);
public static Point2d operator -(Point2d a, Vector2d b);
public static Vector2d operator -(Point2d a, Point2d b);
public static Point2d operator *(Point2d a, double value);
public static Point2d operator *(double value, Point2d a);
public static Point2d operator *(Matrix2d mat, Point2d a);
public static Point2d operator /(Point2d a, double value);
public static bool operator ==(Point2d a, Point2d b);
public static bool operator !=(Point2d a, Point2d b);
}
}
namespace Autodesk.AutoCAD.Geometry
{
[DefaultMember("Coordinate")]
[Wrapper("AcGePoint2d")]
public struct Point2d : IFormattable
{
public Point2d(double[] xy);
public Point2d(double x, double y);
public double this[int i] { get; }
public static Point2d Origin { get; }
public double Y { get; }
public double X { get; }
public Point2d Add(Vector2d value);
public Point2d DivideBy(double value);
public sealed override bool Equals(object obj);
public Vector2d GetAsVector();
public double GetDistanceTo(Point2d point);
public sealed override int GetHashCode();
public Vector2d GetVectorTo(Point2d point);
public bool IsEqualTo(Point2d a);
public bool IsEqualTo(Point2d a, Tolerance tolerance);
public Point2d Mirror(Line2d line);
public Point2d MultiplyBy(double value);
public Point2d RotateBy(double angle, Point2d origin);
public Point2d ScaleBy(double scaleFactor, Point2d origin);
public Point2d Subtract(Vector2d value);
public double[] ToArray();
public string ToString(string format, IFormatProvider provider);
public sealed override string ToString();
public string ToString(IFormatProvider provider);
public Point2d TransformBy(Matrix2d leftSide);
public static Point2d operator +(Point2d a, Vector2d vector);
public static Vector2d operator -(Point2d a, Point2d b);
public static Point2d operator -(Point2d a, Vector2d b);
public static Point2d operator *(Point2d a, double value);
public static Point2d operator *(double value, Point2d a);
public static Point2d operator *(Matrix2d mat, Point2d a);
public static Point2d operator /(Point2d a, double value);
public static bool operator ==(Point2d a, Point2d b);
public static bool operator !=(Point2d a, Point2d b);
}
}