|
I stripped the implementation down and got this:
IDisposable DisposableEvent;
...
DisposableEvent = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
h => MyClass.PropertyChanged += h,
h => MyClass.PropertyChanged -= h)
.Where(evt => evt.EventArgs.PropertyName == "Name")
.Subscribe(arg => PropertyChanged(arg.Sender, arg.EventArgs));
...
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
DisposableEvent.Dispose();
}
I didnt seem to have a need for the h=>h.Invoke wasnt entirely sure why it was there in the first palce either. Im also a bit confused as to why the arg in Subscribe method returns System.Reactive.EventPattern<PropertyChangedEventArgs> , so that I have to use a delegate in order to use the PropertyChanged void. The last Select(evt => getter(target)) I simpy dont understand at all.
|
|
|
|
|
Kenneth Haugland wrote: The last Select(evt => getter(target)) I simpy dont understand at all.
The FromEvent method returns an IObservable<TEventArgs> instance. Every property change would push the EventArgs to the observers, which wouldn't be particularly useful.
The Select converts the returned value to an IObservable<TResult> , where TResult is the type of the property you're observing. It does this by ignoring the EventArgs , and retrieving the current value of the property instead.
NB: Since it doesn't use a WeakReference , the returned object will keep the target alive, which could potentially cause a memory leak.
It looks like the FromEventPattern method is a better fit.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming wrote: The Select converts the returned value to an IObservable<TResult> , where TResult is the type of the property you're observing. It does this by ignoring the EventArgs , and retrieving the current value of the property instead.
I see, makes sence now.
Richard Deeming wrote: NB: Since it doesn't use a WeakReference , the returned object will keep the target alive, which could potentially cause a memory leak.
Yes, that was the thing I was getting at in the end. The examples around the web seems to jsut wrap the ProeprtyObserver inside a Propertyobserver, only changing the the sender from a straong to a weak referance. They dont really seem to care about the WeakEventManager at all. The reason I liked the first example, was that I could see that I could implement the WeakEventManager directly in it, exchanging the PropertyDescriptor. But seems like that is not nessecary?
|
|
|
|
|
I suspect the Rx libraries have changed since that message was posted in 2011.
In the version I have (2.2.0.0), the FromEvent overload that you're trying to call has the following signature:
IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(
Func<Action<TEventArgs>, TDelegate> conversion,
Action<TDelegate> addHandler,
Action<TDelegate> removeHandler);
The conversion parameter that's causing confusion is a function which takes a single parameter (d ) and returns an EventHandler instance. The parameter is an action which takes a single EventArgs parameter.
Therefore, d.Invoke has the signature:
void Invoke(EventArgs e);
whereas the EventHandler delegate you're trying to return has the signature:
void Invoke(object sender, EventArgs e);
Obviously, those signatures are not compatible. You need to return another lambda method / delegate which matches the EventHandler signature, and passes the second parameter (e ) to the action (d ):
d => (sender, e) => d(e)
These nested lambdas can be quite confusing. Breaking it down, you end up with something similar to this:
private sealed class TheClosure
{
public Action<EventArgs> TheActionToCall;
public void TheEventHandler(object sender, EventArgs e)
{
TheActionToCall(e);
}
}
private static EventHandler Conversion(Action<EventArgs> d)
{
TheClosure closure = new TheClosure();
closure.TheActionToCall = d;
return closure.TheEventHandler;
}
...
Func<Action<EventArgs>, EventHandler> conversion = Conversion;
return Observable.FromEvent<EventHandler, EventArgs>(conversion, ...).Select(ignored => getter(target));
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
|
You're feeding a PropertyChangedEventHandler into the Observable but AddValueChanged(..) and RemoveValueChanged(..) expect a plain EventHandler. So for the first argument of Observable.FromEvent(..) you have to create a delegate that takes the PropertyChangedEventHandler and returns an EventHandler:
return Observable.FromEvent<EventHandler, EventArgs>(
propertyChangedHandler =>
{
EventHandler handler = (s, e) => propertyChangedHandler(e);
return handler;
},
h => propertyDescriptor.AddValueChanged(target, h),
h => propertyDescriptor.RemoveValueChanged(target, h))
.Select(x => propertyExpr.Compile()(target)); Or shorter syntax:
return Observable.FromEvent<EventHandler, EventArgs>(
propertyChangedHandler => (s, e) => propertyChangedHandler(e),
h => propertyDescriptor.AddValueChanged(target, h),
h => propertyDescriptor.RemoveValueChanged(target, h))
.Select(x => propertyExpr.Compile()(target));
Edit: Too slow..
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
Yes, working my way through the answers
But I cant get your last line of code to compile, I had to do this:
public static class ObservableEx
{
public static IObservable<TResult> FromPropertyChanged<T, TResult>(T target, Expression<Func<T, TResult>> property)
{
Contract.Requires(target != null);
Contract.Requires(property != null);
var body = property.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The specified expression does not reference a property.", "property");
var propertyInfo = body.Member as PropertyInfo;
if (propertyInfo == null)
throw new ArgumentException("The specified expression does not reference a property.", "property");
string propertyName = propertyInfo.Name;
var propertyDescriptor = (from p in TypeDescriptor.GetProperties(target).Cast<PropertyDescriptor>()
where string.Equals(p.Name, propertyName, StringComparison.Ordinal)
select p)
.Single();
if (!propertyDescriptor.SupportsChangeEvents)
throw new ArgumentException("The specified property does not support change events.", "property");
var getter = property.Compile();
return from e in Observable.FromEvent<EventHandler, EventArgs>(
propertyChangedHandler => (s, e) => propertyChangedHandler(e),
h => propertyDescriptor.AddValueChanged(target, h),
h => propertyDescriptor.RemoveValueChanged(target, h))
select getter(target);
}
}
And the result will only return the actual value thats changed, not the sender and event args.
|
|
|
|
|
Kenneth Haugland wrote: But I cant get your last line of code to compile Sorry, I renamed property to propertyExpr (because it's an Expression) without mentioning it.
Kenneth Haugland wrote: And the result will only return the actual value thats changed, not the sender and event args. That's the case for all the so far shown solutions in this thread. If you want to have the sender and event args you would have to change some stuff:
public class PropertyChangedResult<TTarget, TProperty>
{
public TTarget Target { get; private set; }
public TProperty Value { get; private set; }
public EventArgs EventArgs { get; private set; }
public PropertyChangedResult(TTarget target, TProperty value, EventArgs e)
{
Target = target;
Value = value;
EventArgs = e;
}
}
public static IObservable<PropertyChangedResult<TTarget, TProperty>> FromPropertyChanged<TTarget, TProperty>(TTarget target, Expression<Func<TTarget, TProperty>> propertyExpr)
{
Contract.Requires(target != null);
Contract.Requires(property != null);
var body = propertyExpr.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The specified expression does not reference a property.", "property");
var propertyInfo = body.Member as PropertyInfo;
if (propertyInfo == null)
throw new ArgumentException("The specified expression does not reference a property.", "property");
string propertyName = propertyInfo.Name;
var propertyDescriptor = (from p in TypeDescriptor.GetProperties(target).Cast<PropertyDescriptor>()
where string.Equals(p.Name, propertyName, StringComparison.Ordinal)
select p)
.Single();
if (!propertyDescriptor.SupportsChangeEvents)
throw new ArgumentException("The specified property does not support change events.", "property");
return Observable.FromEvent<EventHandler, EventArgs>(
propertyChangedHandler => (s, e) => propertyChangedHandler(e),
h => propertyDescriptor.AddValueChanged(target, h),
h => propertyDescriptor.RemoveValueChanged(target, h))
.Select(e => new PropertyChangedResult<TTarget, TProperty>(target, propertyExpr.Compile()(target), e));
}
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
Sascha Lefèvre wrote: If you want to have the sender and event args you would have to change some stuff:
Thank you. I realize now I have some catching up to do regarding about Lambda Expression Trees[^].
|
|
|
|
|
Is it possible to write code to enable and disable the DNS Client service using c #?
something like:
private void button1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
If possible .... how to do it, and if not possible... I apologize. Thanks.
I mean this:
http://s23.postimg.org/gapmc008r/Capture.png[^]
|
|
|
|
|
Offhand I know how to do it from the command prompt, soooo:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C sc stop dnscache";
process.StartInfo = startInfo;
process.Start();
Quick code cribbed from SO at c# - Run Command Prompt Commands - Stack Overflow[^]. Credit where it's due.
|
|
|
|
|
Many thanks, it works. I ask for one more question. (example, something like)
When I run my program, if the DNS Client = Enabled (button1.Enabled = false, button2.Enabled = true),
and if the DNS Client = Disabled (button1.Enabled = true, button2.Enabled = false)
Thanks.
|
|
|
|
|
|
|
Thank you. I thought the DNS Client. I set the wrong image. I apologize.
|
|
|
|
|
1448281492 is an Utc-Date (as a decimal?) now i will get these date as a date of my time zone.
Can you may help me?
|
|
|
|
|
|
Sascha Lefèvre wrote: DateTime-
Keep in mind that unfortunately, DateTime, ignores time zone.
One should not confuse that with, for example, assuming that it is the same as UTC, because that would be wrong.
One should strive to use DateTimeOffset instead.
|
|
|
|
|
If those are the number of ticks, then it would be januari the first of your epoch year
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
You need to know what the number is. Its possible that the number is the number of ticks, and if so, see the answers above. It could also be a Unix timestamp or a Julian Day number, in which case see my tip here[^]
|
|
|
|
|
Where is this data coming from?
It might actually be a C++ time_t date (seconds since midnight 1970).
Best,
John
-- Log Wizard - a Log Viewer that is easy and fun to use!
|
|
|
|
|
THANKS!
I get it!
item.CreationDate is a value from a database: it's the utcDate
so now I have this code:
string einstellDatumTemp = item.creationDate.ToString();
int unixTimestamp = int.Parse(einstellDatumTemp);
DateTime unixYear0 = new DateTime(1970, 1, 1);
long unixTimeStampInTicks = unixTimestamp * TimeSpan.TicksPerSecond;
DateTime dtUnix = new DateTime(unixYear0.Ticks + unixTimeStampInTicks);
|
|
|
|
|
The number looks to me like a standard Windows Time value and equates to the UTC time 12:24:52 Mon Nov 23 2015. You can use any of the standard .NET DateTime methods to display it as local time, according to your timezone.
|
|
|
|
|
Member 11916735 wrote: as a date of my time zone.
Better be very sure that it is your time zone.
Good to go if that number is being generated by your computer. But if is coming from another source (computer, database, etc) then you need to determine that.
|
|
|
|
|
Hello Eerry Body,
I'm working on an application in C # which allows to upgrade a Postgresql database to another database.
here is my code
namespace insert
{
class Program
{
static void Main(string[] args)
{
string connString = "DSN=pg_prd;Database=RPD;User Id=postgres;Password=*****;";
OdbcConnection conn = new OdbcConnection(connString);
OdbcCommand command = conn.CreateCommand();
command.CommandText = "Select etb,nobl,poidsb from t_thisdet";
conn.Open();
OdbcDataAdapter MyAdapter = new OdbcDataAdapter();
MyAdapter.SelectCommand = command;
DataSet dset = new DataSet("t_thisdet");
DataTable ds1 = new DataTable("ds1");
MyAdapter.Fill(ds1);
conn.Close();
string conn1String = "DSN=testing;Database=RPD;User Id=postgres;Password=****;";
OdbcConnection conn1 = new OdbcConnection(conn1String);
OdbcCommand command2 = conn1.CreateCommand();
conn1.Open();
for (int k = 1; k < ds1.Rows.Count; k++)
{
string etb= ds1.Rows[k][@"etb"].ToString();
string nobl = ds1.Rows[k][@"nobl"].ToString();
string poidsb = ds1.Rows[k][@"poidsb"].ToString();
command2.CommandText="insert into hisdet values ('"+etb+"',"+nobl+","+poidsb+")";
command2.ExecuteNonQuery();
}
conn1.Close();
}
When I run my code I have this error :
System.Data.Odbc.OdbcException: ERROR [42601] ERROR: INSERT has more expressions than target columns;
Error while executing the query.
While the structure of the select query is equal to the structure of the inserte request.
you have some idea about this.
thank you for your help.
|
|
|
|
|