Hallo,
kann der Type einer Instanz eines generischen Objekts weiter verwendet werden?
Also etwas in der Art wie dieses (nicht ausführbar!) :
class Program
{
static void Main()
{
List<int> l1 = new List<int> ();
Type type = l1.GetType ();
List<type> l2 = new List<type> ();
}
}
Eine Möglichkeit die ich sehe wäre mir l1.GetType().ToString.Equals("ein Datentyp") zurück geben zu lassen und für jeden möglichen Typen eine eigene Initialisierung für l2 anzulegen. Aber das finde ich etwas sehr umständlich. Gibt es eine elegantere Lösung?
Leider finde ich keine passenden Beispiele oder ich suche nach den falschen Stichworten.
Beschreib doch mal genau, was Du tun willst und welche Vorteile Du erwartest dann kann man die Anbieten, was man da machen kann.
Ich kann aus dem Konstrukt jedenfalls nicht erkenne, was Du vor hast und wozu das gut sein soll.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Beschreib doch mal genau, was Du tun willst und welche Vorteile Du erwartest dann kann man die Anbieten, was man da machen kann.
Ich kann aus dem Konstrukt jedenfalls nicht erkenne, was Du vor hast und wozu das gut sein soll.
namespace DeviceComfortApp004
{
class Channel<T> : ChannelBase
{
public T Value { get; set; }
public override string ToString()
{
return "" + Value;
}
}
}
namespace DeviceComfortApp004
{
class ChannelBase
{
public Address Address { get; set; }
public string getChannelTyp()
{
return GetType().ToString();
}
public string getChannelAddress ()
{
return Address.ToString ();
}
}
}
namespace DeviceComfortApp004
{
internal class Address
{
//Fields
//Constructors
public Address (int deviceTyp, int deviceNumber)
{
DeviceTyp = deviceTyp;
DeviceNumber = deviceNumber;
}
//Methods
public override string ToString()
{
return DeviceTyp + "." + DeviceNumber;
}
//Properties
public int DeviceTyp { get; set; }
public int DeviceNumber { get; set; }
}
}
Diese Channels sollen verschiedene angeschlossene Geräte darstellen. Z.B. SPS, Usb-Geräte(serials Port mit Treiberbibliotheken) usw. Der User soll nun über die GUI eine neue Klasse erstellen können die die verschiedenen Channels beinhalten (mit CodeDome oder eher Roslyn). Die Klasse soll dann zum Beispiel so aussehen:
namespace DeviceComfortApp004
{
class ApplicationChannels
{
//Fields
public Channel<double> Voltage = new Channel<double>();
public Channel<int> Length = new Channel<int>();
//Constructor
public ApplicationChannels()
{
Voltage.Address = new Address(0, 0);
Length.Address = new Address(0, 1);
}
//Methods
//Properties
}
}
Diese Channels will ich dann wiederum an Threads übergeben welche eine Queue mit zurückgebenen Werten der Geräte befüllt. Problem dabei ist ja, dass wenn ich einen generischen Typen einer Klasse übergeben will diese auch generisch sein muss. Also verwende ich meinen Basistypen von Channel ChannelBase als Übergabeparameter. Kann ich ja wieder zurück Konvertieren um an Value zu kommen.
Aber irgendwann muss ich ja auch wieder auf meine instanzieren Wert Value in der ChannelBase Instanz zugreifen und muss den tatsächlichen Typen wissen und eine Variable von genau diesem Typen angelegen können. Am besten ohne, dass ChannelThread selbst generisch sein muss... (siehe TRY/CATCH)
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace DeviceComfortApp004
{
class ChannelThread
{
//Gibt Wert von Channel zurück
//generische Behandlung?
private bool _shouldStop = false;
public string value;
private ChannelBase ChannelBase;
private Stream Stream;
private int Clock;
public ChannelThread (ChannelBase channelBase, int clock)
{
ChannelBase = channelBase;
Clock = clock;
}
public void TcpServerConnect(TcpClient tcpClient)
{
try
{
Stream = tcpClient.GetStream();
Console.WriteLine("TCP Server connected \n");
_shouldStop = false;
}
catch (Exception exception)
{
Console.WriteLine("TCP Server communication error\n" + exception.GetType());
}
}
public void Run()
{
Stopwatch watch = new Stopwatch ();
watch.Start ();
while (!_shouldStop)
{
watch.Reset ();
try
{
//HIER SOLL DER AKTUELLE WERT AUS DEM DEVICE
//THREAD GELESEN UND DANN GESENDET WERDEN!
value = (Channel<HIER DOOF>)ChannelBase.Value.ToString ();
Byte[] sendBytes = Encoding.ASCII.GetBytes(DateTime.Now.ToString() + " |> "+ value + "\r\n");
Stream.Write (sendBytes, 0, sendBytes.Length);
}
catch (Exception exception)
{
Console.WriteLine ("TCP communication error\n" + exception.GetType ());
}
Thread.Sleep(Clock - (int)watch.ElapsedMilliseconds);
}
}
public void ShouldStop()
{
_shouldStop = true;
}
}
}
Ich hatte diesen Artikel im MSDN gefunden:
https://msdn.microsoft.com/de-de/library/b8ytshk6%28v=vs.110%29.aspx
Aber dort wird im zweiten Beispiel Punkt zwei auch vorrausgesetzt, dass der spätere Typ (string und Example) zur Laufzeit bekannt ist.
Hi #CPferdchen,
es geht also um diese Code-Stelle:
//HIER SOLL DER AKTUELLE WERT AUS DEM DEVICE //THREAD GELESEN UND DANN GESENDET WERDEN! value = (Channel<HIER DOOF>)ChannelBase.Value.ToString ();
Warum wandelst du den Wert erst in eine Zeichenkette um, nur um ihn dann wieder auf deinen eigentlichen Typ zu casten? Es würde doch reichen, zu schreiben:
var value = ChannelBase.Value;
Wenn du einen (abstrakten) Basistyp definierst, kannst du auch folgendes schreiben:
public class ChannelBase<T> where T : SomeBaseClass
{
public T Value { get; set; }
// ...
}
SomeBaseClass value = ChannelBase.Value;
Wenn ich mir deine Anforderungen allerdings so anschaue:
Der User soll nun über die GUI eine neue Klasse erstellen können die die verschiedenen Channels beinhalten (mit CodeDome oder eher Roslyn).
dann würde ich aber empfehlen, dir zuerst einmal ein geeignetes Datenmodell zu entwerfen, das auch allen deinen Anforderungen entspricht. Das geht sicher auch ohne Reflection/CodeDom/Roslyn, sondern mit herkömmlicher objektorientierter Programmierung.
Christian
Weeks of programming can save you hours of planning
Aber irgendwann muss ich ja auch wieder auf meine instanzieren Wert Value in der ChannelBase Instanz zugreifen und muss den tatsächlichen Typen wissen und eine Variable von genau diesem Typen angelegen können.
Für den Code, den du da gezeigt hast, ist das nicht notwendig.
Du rufst im Endeffekt ja nur ToString() auf und was da raus kommt bestimmt die jeweilige Implementierung von ChannelBase.
edit: zu spät